Skip to main content

Best Practices

Best practices

  • Fail early at input boundaries. Validate incoming data immediately after decoding it. Throw explicit <error> messages for missing or invalid fields before processing begins.
  • Always include a <catch> block in any <try> that wraps code interacting with external systems (databases, APIs, file I/O). Unhandled errors from these sources produce raw technical messages that should never reach the client.
  • Use <finally> for response formatting. Place your <header> and <output> statements in the <finally> block to ensure the response is always sent, even when errors occur.
  • Include enough error detail for troubleshooting but avoid leaking sensitive internals. The details field should help a developer reproduce the issue, not expose database schemas or internal paths.
  • Keep success and failure code paths equally explicit. Use the <else> block for success-only logic rather than assuming "no error means success" at the end of the <try> body.
  • Return consistent error shapes. Every service should use the same JSON envelope structure for errors. Inconsistent error formats create client-side complexity.
  • Wrap system boundaries in try/catch. JSON parsing, HTTP requests, database operations, and any external service calls should always be protected.

Common mistakes

  • Letting parser/runtime errors bubble to the client unchanged. Without <try>/<catch>, a <decode:json> failure produces a raw "Syntax error" message as the entire response — no JSON wrapper, no HTTP status code, no content type header.
  • Returning different error shapes per endpoint. This forces every client to handle errors differently for each API call.
  • Swallowing exceptions without recording context. An empty <catch> block hides failures, making debugging extremely difficult.
  • Placing output statements after the <try> block instead of in <finally>. If an error occurs and the <catch> block doesn't produce output, the client receives an empty response.
  • Setting HTTP status and response payload inconsistently. For example, returning a 200 status with an error payload, or a 500 status with a success payload.
  • Using <error> for control flow instead of <if>/<return>. While <error> works for early exits, it incurs the overhead of exception handling. For expected conditions (like "record not found"), use <if> with <return> instead.