this post was submitted on 22 Mar 2025
752 points (99.0% liked)

Programmer Humor

21893 readers
1976 users here now

Welcome to Programmer Humor!

This is a place where you can post jokes, memes, humor, etc. related to programming!

For sharing awful code theres also Programming Horror.

Rules

founded 2 years ago
MODERATORS
 
you are viewing a single comment's thread
view the rest of the comments
[–] eager_eagle@lemmy.world 45 points 5 days ago (3 children)

That's not what HTTP errors are about, HTTP is a high level application protocol and its errors are supposed to be around access to resources, the underlying QUIC or TCP will handle most lower level networking nuances.

Also, 5xx errors are not about incorrect inputs, that's 4xx.

[–] makuus@pawb.social 27 points 5 days ago (3 children)

…HTTP is a high level application protocol and its errors are supposed to be around access to resources…

I’ve had fellow developers fight me on this point, in much the same way as your parent post.

“If you return a 404 for a record not found, how will I know I have the right endpoint?”

You’ll know you have the right endpoint because I advertised it—in Open API, in docs, etc.

“But, if /users/123 returns a 404, does that mean that the endpoint can’t be found or the record can’t be found?”

Doesn’t matter. That resource doesn’t exist. So, act appropriately.

[–] boonhet@lemm.ee 9 points 5 days ago

Standardize a response body across your APIs that specifies the cause of the non-2xx response. Have an enum per API/service for causes. Include them in the API doc.

If anyone still doesn't get it, quietly dispose of them at your friend's pig farm.

[–] Takumidesh@lemmy.world 4 points 4 days ago

It's not like you can't return a body with the 404 that specifies that the user itself is not found versus the ending being wrong.

[–] prowe45@lemmynsfw.com 3 points 5 days ago (2 children)

And it's not even always a simple case of "that resource doesn't exist". A 404 could also mean that the resource does exist but the current authenticated user doesn't have the correct permissions to access it, so it's more like "as far as you know that resource doesn't exist". Some people might argue that 403 should be used for that, but then you're telling potential bad actors that maybe shouldn't even have access to your documentation that they have indeed found a valid endpoint.

[–] SpaceCowboy@lemmy.ca 7 points 4 days ago (3 children)

Avoiding 403 seems like a security through obscurity approach to me.

I suppose there might be some special admin only endpoints you'd want to 404 on if the user is not an admin. But for most cases it's really hell integrating an API that 404s on everything... is my token invalid, did I set a parameter wrong, or did I get the path wrong? I guess I gotta spend all day doing trial and error to figure it out. Fun!

Also makes integration tests on your security unreliable. Someone renames an endpoint and suddenly your integration tests aren't actually testing security anymore. Checking for 403 and getting a 404 because someone renamed something will indicate the test needs to be updated to use the new path. Checking for 404 (because the user isn't supposed to have access) and getting 404 (because the path was changed) means your test is useless but you won't know it was rendered useless.

[–] eager_eagle@lemmy.world 3 points 4 days ago* (last edited 4 days ago)

It depends on the context. If it's an URL that is easy to guess and reflects user-created content, your system is leaking information about their users if it returns 403. The example that comes to mind is GitHub returning 404s for both nonexisting and private repos when the authenticated user doesn't have access to it.

[–] ByGourou@sh.itjust.works 2 points 4 days ago

Some osint tools use this : they test an email on thousands of services, and use the error result (403/404) to know if the person has an account there.

[–] deur@feddit.nl 1 points 4 days ago* (last edited 4 days ago)

No.

404 is for "I can not confirm this resource exists"

For example, a private github repo must return 404 for unauthorized users, API requests must act as if that repository doesn't exist (including returning 404 status codes).

403 is for "I can confirm this resource exists, you cannot access it"

[–] jerkface@lemmy.ca 1 points 4 days ago* (last edited 4 days ago)

I usually treat a path as a series of dereference operations, each with a potential security precondition. You could protect /secure/... with credential checks, and report 403 at that point, before even looking at the rest of the resource path. It exposes the prefix but not the multiple endpoints that might exist below that point.

[–] bananoidandroid@feddit.nu 1 points 5 days ago (3 children)

The parser in most APIs will automatically handle parsing responses for 400 errors, but if the logic fails due to data being wrong, what do you respond with? E.g you send a valid SSN but the database could not find the person, or you send a valid email, but bo such email was found.

[–] xthexder@l.sw0.com 15 points 5 days ago (1 children)

You can send 4xx errors yourself too. If the client needs to change something about the request, that's a 4xx, like 400 Bad Request. If the server has an error and it's not the client's fault, that's a 5xx like 502 Bad Gateway.

The wikipedia listing of all HTTP codes is quite helpful. People also forget you can send a custom response body with a 4xx or 5xx error. So you can still make a custom JSON error message.

[–] bananoidandroid@feddit.nu 1 points 5 days ago (1 children)

Obviously you can, and i do returm 4xx codes if the initial parsing, authentication or something else goes wrong im the controller, but once im in the next api, or any number of systems down the chain, im probably gonna return a 200 with a status with a tracking code. It's proven, at least for us very helpful to find issues fast on both sides. To me getting a 4xx back when it's step 6 our of 13 that is the problem in the API but the request itself is fine doesn't seem meaningful and just makes customers assume things. I guess if every endpoint only does one thing, i'd probably do like you.

[–] eager_eagle@lemmy.world 9 points 5 days ago* (last edited 5 days ago) (1 children)

A 2xx means success to its requester. If you have an error in step 6 out of 13 that breaks the resource action, you shouldn't be returning a success.

You might argue what to return and what kind of information to include in the response (like tracking numbers), but it shouldn't be a 2xx and I don't see how a misleading 200 would be more helpful than a 400 bad request.

[–] bananoidandroid@feddit.nu 1 points 5 days ago (1 children)

I mean sure, in the strict meaning of the code-guides you are probably correct. Most problems stems for us at least from cross-reference issues which are normally configuration problems in the underlying system or other data-related issues. Those are often not neither the responsibility of the server or the client, and sometimes its both. There are often no code that is suitable to respond, and to just send "Bad request" when it's a good request - does not make sense. Therefore i think it's better to let badrequest be for bad requests, instead tell the client that sure, this is a good request but for this reason it didn't work this time. This has to happen for it to work. Either i can do it with a simple structure in json with maybe 5 status codes and a message, or i have to figure out what 20 http status codes both i and the client has to implement and give them meaning that isn't their intended meaning.

[–] eager_eagle@lemmy.world 5 points 5 days ago (1 children)

and to just send “Bad request” when it’s a good request - does not make sense

That's when you use a 5xx status, then. The client doesn't care how many other services you reach out to in order to fulfill their request. A 5xx code also covers failures in other parts of the system.

[–] bananoidandroid@feddit.nu -1 points 4 days ago (1 children)

The customer expects a row to exist. The server does not find it.

The customer sent a valid request, and it should exist according to the customer.

The server could not find it. It can find others, but not that one, so from the server perspective it's the client that gave the wrong id. If i always send a 404, the customer system think it did something wrong, which it didnt. Should they try to find the error on their side now, as it is a "client error"?

If i send a 500 every time, the customer will think the server is at fault, which it is. The server just could not find that row. What if the customer actually made an error, sending the wrong id, and i send the same code every time. It will be the servers fault every time the customer makes an error, and now they will never double check their inputs.

My point is, there is no nuance with these old codes. Obviously i will send a 500 for a caught exception and a 400 for a client error, but it is not always so easy.

[–] pupbiru@aussie.zone 6 points 4 days ago* (last edited 4 days ago) (1 children)

error codes aren’t about who’s at fault… you don’t send a 404 because it’s the users or the servers fault. it’s information… a 404 says something doesn’t exist… it’s nobody’s fault; it just is

a 4xx says the request, if tried again without changes or external intervention, is unlikely to succeed

a 5xx says the request might have been fine but some other problem that you can’t control occurred so may be retried without changes at a later time

these are all standard things that are treated in standard ways by generic HTTP libraries… look at, eg axios: a javascript HTTP library that’s often thinly wrapped to build API clients… a 200 is just passed through as success, where 4xx and 5xx will throw an error: exactly what you’d want if you try to retrieve a non-existent object or submit a malformed payload…

this is standard behaviour for a lot of HTTP libraries, and helps people accidentally write better code - an explosion is better than silence for unhandled exceptions

[–] bananoidandroid@feddit.nu 0 points 4 days ago (1 children)

I get it. I'm just trying to illustrate why i like to differ between com and app errors. Now we have identified three different scenarios, all returning 404. Resource not found Data not found (client error). Data not found (server error). when we could treat them different because their nature is fundamentally different. I mean if we request a list of objects and nothing was found, because we asked for a date when there was no data, its not an error. But i suppose many still just throw around exceptions still instead of handle them properly, and it looks terrible in the log. Imo if i know the reason for a behaviour its not necessarily an error, and using an error code for a non-error makes it harder to find real errors. Maybe i've just been turned off by how they have been used in our legacy code. Maybe you don't define 404 as a client side and not an error, and i guess thats fine. But its pretty counterintuitive to be a number in a list of client errors and be anyrhing but.

[–] pupbiru@aussie.zone 3 points 4 days ago* (last edited 4 days ago) (1 children)

Resource not found Data not found (client error). Data not found (server error)

they are all the same thing; there is no useful, practical distinction between them

if we request a list of objects and nothing was found, because we asked for a date when there was no data, its not an error. But i suppose many still just throw around exceptions still instead of handle them properly

it’s an empty array: not found when requesting something specific is an error… that’s different to here is the complete set of 0 objects… like like if you have an array and request an index that doesn’t exist you get an exception, but that doesn’t mean an empty array is exceptional: it is in fact very valid

using an error code for a non-error

well, it is an error though. you have requested a URI for an object that doesn’t exist: it doesn’t matter whether it’s a resource or an individual thing

remember that HTTP youre asking the server for some object matching a URI: please give me the object matching /users/bananoidandroid and /userssssss/bananoidandroid may both not be found for the exact same reason: the object referenced by that string does not exist

here’s the spec definition for 404

The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

when you’re dealing with specs, deciding not to follow them because you feel like they’re wrong is not appropriate… this leads to bugs and issues in compliant tools because they make assumptions about what things mean

200 means the thing that you asked completed successfully

here’s the definition of 200:

The request has succeeded. The information returned with the response is dependent on the method used in the request, for example:

GET an entity corresponding to the requested resource is sent in the response;

HEAD the entity-header fields corresponding to the requested resource are sent in the response without any message-body;

POST an entity describing or containing the result of the action;

TRACE an entity containing the request message as received by the end server.

*edit: when talking about compliant, standard tools the classic example is transparent cache: a GET should not transform the resource and thus a GET with response of 200 can be cached… an API that uses a GET to modify a resource may cause transparent proxies (or CDNs) to significantly mishandle the user request… same goes for 200 vs 4xx and 5xx: proxies know that 200 means what it means and may cache based on that, where 5xx should never be cached and 4xx is probably dependant on which specific 4xx

[–] bananoidandroid@feddit.nu 1 points 4 days ago

Of course there is. Maybe in your line of work and set of "standard" tools there is no distinction, and everything is a world of simple rules. For me, handling an error based on a response is what you are supposed to do. If you do not differ between them, you'll just spend time to figure it out by hand.

[–] Thorry84@feddit.nl 2 points 5 days ago

That's still a 4xx situation.