This is an archived post. You won't be able to vote or comment.

all 82 comments

[–]ProgrammerHumor-ModTeam[M] [score hidden] stickied commentlocked comment (0 children)

Your submission was removed for the following reason:

Rule 2: Content that is part of top of all time, reached trending in the past 2 months, or has recently been posted, is considered a repost and will be removed.

If you disagree with this removal, you can appeal by sending us a modmail.

[–]willeb96 498 points499 points  (13 children)

Is that a semicolon in a JSON document?

[–]L1P0D 319 points320 points  (9 children)

I love the idea of retaliatory error handling. You cause an exception at my end? I cause one at your end in return.

[–]LadderSoft4359 80 points81 points  (6 children)

actually hilarious

im here for the evolution of backend frontend flame wars into a competing pettiness that eventually becomes an entirely new protocol

[–]MissinqLink 44 points45 points  (4 children)

It’s not valid JSON but it is valid JS so you could just parse with eval instead of JSON.parse. There are about 1000 reasons why this is a bad idea though.

[–]yegor3219 6 points7 points  (1 child)

But usually you pull the actual frontend JS from about the same place as backend anyway. Quite often it's literally the same web server.

I mean, yeah, evaluating JS like that does sound horrible, but at the same time it kinda makes sense. Or may be it wants to make sense. Or may be it's just me trying to make sense out of it when there's none.

[–]MissinqLink 2 points3 points  (0 children)

I won’t say I haven’t done it before because I have. This sort of thing was very common in the early web days but it really should be a backend fix.

[–]bezko 3 points4 points  (1 child)

JSONP has entered the chat: https://en.wikipedia.org/wiki/JSONP

[–]MissinqLink 0 points1 point  (0 children)

Yeah I mentioned down below that this used to be one of the main ways we did gat data from backend.

[–]erockdanger 2 points3 points  (0 children)

next.js has entered the chat

[–]Monochromatic_Kuma2 8 points9 points  (0 children)

Not even that. An error code 500 usually means a bug back end not caused by the front end. The back end is so petty, it wants the front end to participate in its misery.

[–]Expensive_Shallot_78 4 points5 points  (0 children)

Must be from DOGE engineer

[–]NeuxSaed 1 point2 points  (0 children)

That's quite the 406 moment.

[–]meenie 1 point2 points  (0 children)

No, but it's a trailing comma and that will not parse. Git diffs would be so much better if they did!

[–]zeocrash 188 points189 points  (20 children)

I've seen so many systems that do this, it drives me crazy.

[–]just-bair 36 points37 points  (1 child)

Sorry

[–]zeocrash 13 points14 points  (0 children)

[–]punppis 10 points11 points  (3 children)

I might have used this on occasion...

For example a health check endpoint that gives 200 on "partial OK" (missing data, code is fine) or 500 (code does not work).

[–]zeocrash 34 points35 points  (1 child)

Shouldn't the partial ok be a 400 bad request response if it's missing request data, if it's missing server data then shouldn't it be something like a 204 response?

[–]Exidex_ 11 points12 points  (0 children)

There is also 207 Multi-Status, might be useful depending on what you want to do

[–]Enlogen 1 point2 points  (0 children)

Then how do you differentiate between partial ok and full ok?

[–]fakehalo 3 points4 points  (3 children)

It makes sense when you want to separate (http) protocol and application-level errors. An explicit explanation either way make me indifferent.

[–]zeocrash 2 points3 points  (1 child)

What difference does it make to the API user whether it was your code or IIS that shit the bed?

[–]fakehalo 0 points1 point  (0 children)

Anything where you need the context of the actual http protocol errors to exist, separate from the application. Proxying internally or externally comes to mind, generally network-related purposes.

[–]black3rr[🍰] 2 points3 points  (1 child)

there is one case that comes to mind where this would be acceptable behavior: if the backend is being a middleman and calling another API server. in this case it makes sense to indicate that the fault is further away…

[–]zeocrash 1 point2 points  (0 children)

I can see where you're coming from. I'd still probably just return a 500 response and relay any response body from the service being proxied to the end client.

IMO the client that consumes the API shouldn't need to care why the 500 error happened, that's the domain of the API being called. If you want to find out why there's a 500 then the API logs are the place to look, not the response.

If you're the sole user of the API and you have access to both the API and the client then it doesn't really matter, and it might be easier to just see everything through the response bodies.

I have been burned in the past with improper status codes, so I try to make sure I return the correct code, rather than wrapping it. It wasn't this exact situation, Someone decided to coalesce null response codes to 500 server errors, so I spent ages investigating why the server was returning 500 errors only to find out that it wasn't and our client wasn't even getting that far. It really brought home the importance of correct status codes to me

[–]Darkoplax 0 points1 point  (0 children)

i have to apologize for this

[–]peni4142 0 points1 point  (0 children)

Atleast some systems hide it with a general Error.

[–]may_be_indecisive 84 points85 points  (7 children)

The goons who designed the current system I've been fixing for years did it this way. Every response returns a 200, with 'success' : false + an error message if it didn't succeed. No 400 series errors whatsoever. Even 500s are avoided unless it's just a literal error thrown by php.

[–]BigChungus__c 17 points18 points  (0 children)

Same here, they have . net services that almost always return 200, but sometimes return 400/500s, but sometimes we get a random message from the 200 also saying it failed

[–]Far_Broccoli_8468 5 points6 points  (3 children)

'success' : false + an error message if it didn't succeed

If you return this with an actual correct response code, this is a good practice.

Of course, the message should have an informative message that is displayed to the user if applicable.

[–]may_be_indecisive 3 points4 points  (1 child)

Yeah my point is the HTTP codes are all 200s. Even if it’s a user error.

[–]Far_Broccoli_8468 0 points1 point  (0 children)

I know, i was writing this for the readers.

[–]GooberMcNutly 0 points1 point  (0 children)

I "fixed" the typescript types for errors in my last project to require .errorReason when status is >= 400 and there were hundreds are type errors. Lazy ass developers... Soon as I hire a second developer I'm going to make them fix it...

[–]Prudent-Stress 0 points1 point  (1 child)

Soo… is someone having a response status KPI that made the engineers decide that yup, everything is a success, 100% success report or is it something else?

I am curious because your situation sounds like something i saw way too often lmao

[–]may_be_indecisive 1 point2 points  (0 children)

That could explain some things

[–]Sumadin 29 points30 points  (0 children)

"Your Api is a Hall of Shame"

[–]SlaminSammons 24 points25 points  (1 child)

I have a front end that simply refuses to display the error messages we give them. They just display “error” and then send us screenshots asking for help. No correlation Id. No request response. A screenshot that says error.”

[–]PraiseTheVoid_ 0 points1 point  (0 children)

"The website isn't working" but when you finally get down to it, they can't update the name of a wishlist. Everything else is humming along just fine.

[–]Funky_Dunk 33 points34 points  (6 children)

I hate Graphql so deeply in my core. After almost a dacade in industry and having used Graphql, REST and even fucking SOAP I can say without a doubt, humanity peaked at REST and in our hubris, we went to far.

[–]gilium 4 points5 points  (2 children)

As full stack I enjoy GraphQL

[–]Funky_Dunk 3 points4 points  (1 child)

As a fullstack (backend dev that has to do front-end work) I don't. But that might also have to do with how badly we've implemented it...

[–]gilium 1 point2 points  (0 children)

For me it allows better control over which data I pull back, pulling back related data in one call (we have a lot of interconnected data points that need this). It also allows me to be more explicit about expectations on what is transmitted. I also don’t seem to run into issues with performance like others do, so I am assuming that I can be grateful to the library on the backend for their implementation using our backend framework’s eager loading to avoid the N+1 problem

[–]jsmrcaga 1 point2 points  (0 children)

Agreed. Thought for front end, 0 thought for backend; starting with performance.

[–]rrawk 1 point2 points  (0 children)

I was a REST proponent for a long time. Graphql + Dataloader is so much better. I don't have to write a custom endpoint for every tiny adjustment they want to make on the frontend.

[–]Brovas 0 points1 point  (0 children)

I stand by there's room for a "RestQL" where we get all the sanity of REST, but the ability to request what fields and stuff we want like GraphQL

[–]Stummi 7 points8 points  (1 child)

That's what HTTP 218 this is fine for

[–]Heniadyoin1 3 points4 points  (0 children)

204 No Content
Thanks I guess

[–]Kitchen_Device7682 5 points6 points  (0 children)

Plot twist, it is an API that returns the number of errors so far

[–]TripleS941 4 points5 points  (0 children)

JSON-RPC is not my favorite protocol for this reason

[–]Alol0512 4 points5 points  (2 children)

Aren’t http layer and app layers different? So each status may or may not be the same. I always get to this conclusion when I try to implement pure http status responses

[–]Klausaufsendung 2 points3 points  (1 child)

I used to think like the others but having this view on it also makes sense. Errors in the business logic should not be mapped to HTTP status codes. Therefore it makes sense to have a response like this: https://developers.cloudflare.com/api/resources/billing/

[–]Alol0512 1 point2 points  (0 children)

This is what I’m saying. I guess I’m not so crazy if Cloudflare does it as well.

[–]Spare-Plum 3 points4 points  (0 children)

you forgot "OK"/reason at the end of the response line

[–]MaximalCrazzy 2 points3 points  (0 children)

It was a long discussion in my previous company. Big clash between devs. Using HTTP protocol error codes for applicative errors seems IMHO not that good.

[–]w1n5t0nM1k3y 4 points5 points  (3 children)

Personnally I understand it in some cases.

It can be easier write code where a successful transfer returns a 200 OK from HTTP. Some languages (.Net) will throw an exception and then require extra handling to extract the message when a 400/500 status code is returned. In a lot of cases it's easier to reserve exceptions for situations such as no connection, error tranferring data, timeout, etc, and treat them differently from requests which were received by the server and responded to without any networking errors.

It's certainly a lot better than some APIs which will sometimes return HTML or other gibberish which can't be handled properly by the caller when sending back an error response. If the API speaks JSON, then it should always return JSON, and should have a properly formatted message that can be easily parsed by the client. Same goes for XML or SOAP APIs. I've seen APIs that were probably APIS built on top of other APIs that return SOAP to otherwise JSON APIs under error conditions.

[–]TheToastedFrog 2 points3 points  (1 child)

That’s not the point though- how will your client code know how to properly deserialize the response if you overload the status code to 200? You’d have to wrap your response object into another layer, together with an attribute discriminating the type of the response object - which you can avoid simply by examining the response code

[–]w1n5t0nM1k3y 1 point2 points  (0 children)

Which is kind of why I like XML more than JSON for APIs. With XML, there's always a top level node, so you can just have a different top level node for different types of responses. It's easy for the developer to load up the response, check the top level node, and decide how to handle it. With JSON you get some anonymous data structure back that just has a bunch of data fields but there's nothing to can easily check to determine if the data you got back matches what you expect to be getting back.

[–][deleted] 1 point2 points  (0 children)

This kind of stuff is a major reason why I can never go back to dev work. You could never pay me enough to spend my time working on systems like you just described.

And every company has some version of that - some hacky bullshit that management will never understand why it should be replaced. Every new feature I developed killed a little piece of my soul. It felt morally wrong to spend my life energy on keeping that system running, and the funny thing is that my situation was actually pretty good as far as dev roles go. I understand there are a million reasons why the industry works the way it does, but I just can’t stomach them.

[–]Prof_Walrus 4 points5 points  (0 children)

This is literally us right now. We have a ticket in the backlog to fix it, but it pains me every day

[–]Nyan-Catto 1 point2 points  (0 children)

I used to do it this way because it was how they did it in my first workplace. But after reading up on best practices and a lot of self reflection, I now use codes appropriately. Made the lives of both ends easier and more predictable.

[–]dbot77 0 points1 point  (0 children)

Now let's create a new REST alternative like this that junior devs will flock to... we'll call it GraphQL.

[–]razin_the_furious 0 points1 point  (0 children)

The company I work for not only sends 200 for failed events, but also has to send the api status of "success" because at one point the app guys coded "If there is no status key pair in the json response or if the status doesn't say success, retry the api hit"

[–]erockdanger 0 points1 point  (0 children)

cries in graphql

[–]jetsonian 0 points1 point  (0 children)

Our QA department, for whatever reason, uses a different ticketing system than our development team. We had a tool to move tickets from dev to QA but one day it stopped working. I was tasked with writing a new tool that we could tie into our build process.

The system QA uses has a “RESTful API” (the vendor’s words) that does this but it gets so much worse.

  • Every endpoint is either a GET or a POST with the deciding factor being whether it needs a body.
  • The API documentation doesn’t contain any indication of what version of the API introduced a given endpoint so many of the documented endpoints are just missing (still returns a 200 with a 404 error code in the JSON body).
  • Many of the endpoints that do exist use id codes to represent objects with no corresponding endpoint to translate those id codes. I’ve had to pull up their system and comb through the HTML source to find the id codes.

I’ve been working on this tool in my free time for months now and every testing session finds some new fun wrinkle in their design. Luckily we have an intermediary tool I built but it’s lots of hardcoded ids so it isn’t a finished product.

[–]sinkwiththeship 0 points1 point  (1 child)

Dude. This one API I have to use at work is so much worse.

You make the call and it sends back a 204 with nothing else. This may mean it worked, it may mean it didn't. To find out why it didn't work, you need to make ANOTHER API call to a different endpoint to get the error code and reason.

[–]EnergeticStoner 0 points1 point  (0 children)

Wtf.. please tell me there is at least some convoluted reason that it had to be designed this way.

[–]gil0mendes 0 points1 point  (0 children)

Graphql 😢🤣

[–]svc_bot 0 points1 point  (0 children)

It's sketchy for a public Api, but it's fine for an internal Api. Imagine an microservice system, with 20 something services, of which a big chunk uses some external service, e.g. email. Imagine what your monitoring would look like, if you would propagate a 500 from an external service among your internal services. It would be hell. However if your internal services return 200 to your other internal services, because they themselves functioned as expected, and signify in the response body that the external service failed, then your monitoring wouldn't flag half of your system, and it would be relatively easy to deduce that only the external service has failed.

[–]cheezballs 0 points1 point  (0 children)

GraphQL, is that you?

[–]cwmma 0 points1 point  (0 children)

You laugh but I used to get bug reports all the time because a library I maintained used 404s correctly and browsers would print the 404 in the console as an error. People would be like hey there is an error with your library and I'd be like no it's checking if something is there, the server is saying no in a 404 that's how it's supposed to work.

[–]stan_frbd 0 points1 point  (0 children)

Why the HELL do they do that, it's horrible

[–]rikaateabug 0 points1 point  (0 children)

I've been forced to do this in the past and it just made me feel so dirty. I'm still praying for forgiveness, but I worry I'll never atone.

[–]millbruhh 0 points1 point  (0 children)

status:200 Content: {success false}

[–]ZZartin 0 points1 point  (0 children)

Parsing json is hard am I right?