relay icon indicating copy to clipboard operation
relay copied to clipboard

@catch documentation

Open jantimon opened this issue 6 months ago • 5 comments

I am unsure how @catch and @throwOnFieldError work and have the feeling that it's not explicitly covered in the docs

Given this scenario:

query MyQuery {
  viewer @catch {
    ...throwingFragment
  }
}

fragment throwingFragment on Viewer @throwOnFieldError {
  name
  age
}

Does the @catch on the parent query field catches @throwOnFieldError in the fragment similar to try/catch?

My understanding is that @catch creates a boundary that prevents exceptions from propagating up converting them to the { ok: false, errors: [...] } format instead

The docs mention "@catch tells Relay that you don't want a JavaScript exception" but it would be helpful to explicitly explain this behavior for fragments with @throwOnFieldError nested under @catch

Thanks in advance

jantimon avatar Aug 07 '25 05:08 jantimon

Good callout. Let me open a diff.

captbaritone avatar Aug 07 '25 16:08 captbaritone

thanks @captbaritone for the clarification

They do not handle errors related to fields in any spread fragments.

is that also true for fragment with @inline?

for example:

query MyQuery {
  viewer @catch {
    ...throwingFragment
  }
}

fragment throwingFragment on Viewer @throwOnFieldError @inline {
  name
  age
}

jantimon avatar Aug 12 '25 11:08 jantimon

here are even more questions I got asked by coworkers which might need some more docs:

would this @catch catch as brandById is a direct field access - or would it not catch as data is only loaded in spreaded fragments?

query brandPageQuery(
      $id: ID!
 ) @catch {
    brandById(id: $id) {
        ...brandOverview
    }
}

would this @catch catch - or does it behave differently for __typename?

query MyQuery {
  viewer @catch {
     __typename
    ...throwingFragment
  }
}

fragment throwingFragment on Viewer @throwOnFieldError {
  name
  age
}

jantimon avatar Aug 18 '25 08:08 jantimon

Looks like @catch and @inline have a bug. I'll reply on https://github.com/facebook/relay/issues/5069

In the case you outlined about brandById, @catch would handle errors reported by the brandById field, but not any of the fields within the ...brandOverview. The "tip" at the top of the docs page should clarify that @catch does not handle errors thrown within a spread fragment: https://relay.dev/docs/guides/catch-directive/

captbaritone avatar Sep 25 '25 16:09 captbaritone

While it is generally true, that @catch and also @throwOnFieldError only handle errors for fields referenced in the operations that these directives are placed on, this is then not true anymore if you spread a fragment that has the @inline directive. When there is an error associated with a field referenced inside an inline fragment, this will trigger @catch or @throOnFieldError of the fragment that spreads the inline fragment.

Given this behaviour, the "tip" at the top of the docs on relay.dev/docs/guides/catch-directive is incorrect.

christiansany avatar Sep 30 '25 14:09 christiansany