> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.clossir.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.clossir.com/_mcp/server.

# Error Handling

GETTING STARTED · SDK · ERROR HANDLING

The Clossir SDK throws typed exceptions for all API errors. Every 4xx and 5xx response from
the Clossir API returns an [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457.html)
`application/problem+json` body, which the SDK parses into a `SignumProblemDetailsError`.

## Catching errors

```ts title="catch-errors.ts"
import { Signum } from "@signum-tech/sdk";
import {
  SignumProblemDetailsError,
  SignumError,
} from "@signum-tech/sdk/models/errors";

const signum = new Signum({
  serverURL: process.env.SIGNUM_API_URL,
  bearerAuth: process.env.SIGNUM_API_KEY,
});

try {
  await signum.attestations.postAttestations({
    partyId: "pty_abc123",
    type: "accredited_investor",
    chainEid: 30101,
  });
} catch (e) {
  if (e instanceof SignumProblemDetailsError) {
    console.error(e.title);    // "Forbidden"
    console.error(e.status);   // 403
    console.error(e.detail);   // "Organization KYC not approved"
    console.error(e.type);     // "urn:signum:error:kyc-required"
    console.error(e.instance); // "/attestations/abc-123"
  }
}
```

## Error hierarchy

```
Error
└── SignumError (statusCode, body, headers, rawResponse)
    ├── SignumProblemDetailsError (type, title, status, detail, instance)
    └── SignumDefaultError (fallback for non-problem+json responses)

HTTPClientError
├── RequestTimeoutError
├── ConnectionError
├── RequestAbortedError
├── InvalidRequestError
└── UnexpectedClientError
```

`SignumProblemDetailsError` is the primary error type — the API standardizes on RFC 9457
for all error responses. `SignumDefaultError` exists as a fallback but should not occur
under normal conditions.

`HTTPClientError` subtypes represent transport-layer failures (network issues, timeouts)
rather than API responses.

## Type narrowing

TypeScript narrows the type after an `instanceof` check, giving you access to the
structured fields:

```ts title="type-narrowing.ts"
try {
  await signum.transfers.postTransfers({ /* ... */ });
} catch (e: unknown) {
  if (e instanceof SignumProblemDetailsError) {
    // RFC 9457 structured error — all fields available
    switch (e.status) {
      case 409:
        console.log("Conflict — resource already exists");
        break;
      case 429:
        console.log("Rate limited — back off and retry");
        break;
      default:
        console.error(`${e.title}: ${e.detail}`);
    }
  } else if (e instanceof SignumError) {
    // Other HTTP error — has statusCode, body, rawResponse
    console.error(`HTTP ${e.statusCode}: ${e.body}`);
  } else {
    // Network error, timeout, etc.
    throw e;
  }
}
```

## Extension fields

Problem+json responses may include fields beyond the standard RFC 9457 set — for example,
the guard middleware includes resolution hints when a prerequisite check fails. Access
these via the `data$` property:

```ts title="extension-fields.ts"
if (e instanceof SignumProblemDetailsError) {
  const hints = e.data$["resolution_hints"] as string[] | undefined;
  const checks = e.data$["failed_checks"] as string[] | undefined;

  if (hints) {
    console.log("To resolve, try:", hints.join(", "));
  }
}
```

## Branching on error type

The `type` field uses URN-style identifiers that categorize the error. Use it for
programmatic error handling:

```ts title="branch-on-type.ts"
if (e instanceof SignumProblemDetailsError) {
  switch (e.type) {
    case "urn:signum:error:kyc-required":
      // redirect user to KYC flow
      break;
    case "urn:signum:error:compliance-blocked":
      // show compliance rejection reason
      break;
    case "urn:signum:error:insufficient-balance":
      // prompt for funding
      break;
    default:
      // unknown error type — show detail to user
      console.error(e.detail);
  }
}
```

## Standalone functions (Result pattern)

The SDK also exposes standalone functions that return `Result<T, E>` instead of throwing.
This is useful for functional/railway-style error handling:

```ts title="result-pattern.ts"
import { SignumCore } from "@signum-tech/sdk/core.js";
import { healthGetHealth } from "@signum-tech/sdk/funcs/health-get-health.js";

const client = new SignumCore({
  serverURL: process.env.SIGNUM_API_URL,
  bearerAuth: process.env.SIGNUM_API_KEY,
});

const result = await healthGetHealth(client);

if (!result.ok) {
  // result.error is the error — no try/catch needed
  console.error("Health check failed:", result.error);
  return;
}

// result.value is the typed response
console.log("API is healthy:", result.value);
```

## Next steps

* [Retries & Backoff](/getting-started/sdk/retries) — configure automatic retry for transient errors
* [Async Operations](/getting-started/sdk/async-operations) — handle 202 command responses