and no object exists with that exact id the error is not very explicit or useful.
I have a strong preference for explicit error return objects in GraphQL to handle this kind of thing, but the Dato GraphQL is probably not going to adapt those any time soon. So I ask generally, what’s the best way to handle “not found” scenarios like this? Currently I’m running a string comparison on the error message itself, but it feels wrong.
Or if you need a more explicit “this entry is good” check, you can validate post._status==='published' and/or post._isValid===true, perhaps?
I’m not sure of your use case here (why would it ever be looking up a nonexistent ID to begin with?), but if you can provide an example, maybe we can help think of something more suitable?
That’s interesting, I’m definitely not getting null, that would actually be a better scenario. I think I’m hitting some kind of regex checking for the old and new id formats. If you try adding a dash or something to the id to make it invalid looking, what happens?
The reason I’m getting non-existing id’s is just because of some bot traffic I think. I’m just seeing this come up in my logs and don’t want a 500 error but a nice 404.
Forgot to add, this is the error message I’m getting and checking for:
Variable $id of type ItemId! was provided invalid value
I see, thank you for explaining! That does indeed happen if you provide altogether invalid IDs (like if a bot were just scanning for them and making up IDs).
First, I should probably point out that it’s not a great idea to have your page routing directly tied to API lookups, if for no other reason than that this would make for easy denial-of-service attacks from any bot going to your pages (existent or not). You would then have to pay for all their pointless API calls It would be safer to route only to pages (IDs) you know you’ve created and to 404 or redirect other ones by default, unless you are specifically trying to dynamically generate pages for SEO or such.
That will test the ID for validity so you don’t pass it on to the API if it’s junk.
(Edit: The package has since been updated. The below comment is no longer relevant.)
(Outdated, please ignore): Click to expand: Only relevant if your Dato project still has number-only IDs
Side note: If your Dato project is really old, and not using alphanumeric IDs yet (i.e., it still has integer IDs from our past), you can also allow through 6-byte integer IDs (i.e., ints <= 281474976710655). That check is NOT present in the isValidId() option but IS in the GraphQL layer, which is why integer IDs still work there. Newer projects don’t have to worry about this at all.
That helps - and thanks for including that note on integer ID’s - we do indeed have a lot of those. SEO is very important for us so we are just rendering everything dynamically. This check will really help prevent attacks that rack up our billing.
When looking at that code for isValidId, I notice that the first lines are:
// For backward compatibility, first check to see if this is an older-style integer ID formerly used by Dato
if (/^\d+$/.test(id)) {
const intId = BigInt(id);
const maxDatoIntegerId = 281474976710655; // Max 6-byte/48-bit unsigned int
return intId <= maxDatoIntegerId;
}
This directly contradicts your comment that legacy ID checking isn’t supported. Unless I’m misunderstanding something …
Oh, hah, that was fast! I made a PR for that because of your post here. I didn’t expect it to get merged in so soon (it usually takes a few days, but our devs were on it this time!).
That means you can just go ahead and use that code then. Sorry for the confusion. It wasn’t there yet when I first replied
Good call. I’ve asked for a version release and will let you know once it’s up. (If it’s time sensitive, you could also copy that code or fork the repo to get it working sooner).