> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blnkfinance.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Check three-value returns, read structured Core error codes, and handle validation and transport failures with the Go SDK.

export const CtaCallout = props => {
  const {title, buttonLabel, href, trackingEvent, buttonTarget, rel = "noopener noreferrer", children} = props;
  const handleCtaClick = () => {
    if (typeof window === "undefined" || !trackingEvent) {
      return;
    }
    try {
      window.dispatchEvent(new CustomEvent("blnk:docs-cta", {
        detail: {
          name: trackingEvent,
          href
        }
      }));
    } catch {}
    try {
      window.posthog?.capture?.(trackingEvent, {
        href
      });
    } catch {}
    const gaPayload = {
      cta_href: href
    };
    try {
      window.gtag?.("event", trackingEvent, gaPayload);
    } catch {}
    try {
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        event: trackingEvent,
        ...gaPayload
      });
    } catch {}
  };
  const isExternal = typeof href === "string" && (/^https?:\/\//i).test(href);
  const target = buttonTarget ?? (isExternal ? "_blank" : undefined);
  const linkRel = isExternal ? rel : undefined;
  return <section className="cta-callout not-prose relative my-8 w-full min-w-0 overflow-hidden rounded-xl border border-zinc-200 p-5 dark:border-white/10">
      <div className="cta-callout-noise" aria-hidden="true" />
      <div className="cta-callout-layout">
        {title ? <div className="cta-callout-title-row">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" width="14" height="14" className="cta-callout-icon shrink-0 text-zinc-800 dark:text-zinc-200" aria-hidden="true">
              <g fill="none" fillRule="nonzero">
                <path d="M28 0v28H0V0h28ZM14.691833333333335 27.134333333333334l-0.012833333333333334 0.0023333333333333335 -0.08283333333333333 0.04083333333333334 -0.023333333333333334 0.004666666666666667 -0.016333333333333335 -0.004666666666666667 -0.08283333333333333 -0.04083333333333334c-0.011666666666666667 -0.004666666666666667 -0.022166666666666668 -0.0011666666666666668 -0.028000000000000004 0.005833333333333334l-0.004666666666666667 0.011666666666666667 -0.019833333333333335 0.49933333333333335 0.005833333333333334 0.023333333333333334 0.011666666666666667 0.015166666666666667 0.12133333333333333 0.08633333333333333 0.0175 0.004666666666666667 0.014000000000000002 -0.004666666666666667 0.12133333333333333 -0.08633333333333333 0.014000000000000002 -0.018666666666666668 0.004666666666666667 -0.019833333333333335 -0.019833333333333335 -0.4981666666666667c-0.0023333333333333335 -0.011666666666666667 -0.0105 -0.019833333333333335 -0.019833333333333335 -0.021Zm0.3091666666666667 -0.13183333333333336 -0.015166666666666667 0.0023333333333333335 -0.21583333333333335 0.1085 -0.011666666666666667 0.011666666666666667 -0.0035000000000000005 0.012833333333333334 0.021 0.5016666666666667 0.005833333333333334 0.014000000000000002 0.009333333333333334 0.008166666666666668 0.23450000000000004 0.1085c0.014000000000000002 0.004666666666666667 0.026833333333333334 0 0.03383333333333334 -0.009333333333333334l0.004666666666666667 -0.016333333333333335 -0.03966666666666667 -0.7163333333333334c-0.0035000000000000005 -0.014000000000000002 -0.011666666666666667 -0.023333333333333334 -0.023333333333333334 -0.025666666666666667Zm-0.8341666666666667 0.0023333333333333335a0.026833333333333334 0.026833333333334334 0 0 0 -0.0315 0.007000000000000001l-0.007000000000000001 0.016333333333333335 -0.03966666666666667 0.7163333333333334c0 0.014000000000000002 0.008166666666666668 0.023333333333333334 0.019833333333333335 0.028000000000000004l0.0175 -0.0023333333333333335 0.23450000000000004 -0.1085 0.011666666666666667 -0.009333333333333334 0.004666666666666667 -0.012833333333333334 0.019833333333333335 -0.5016666666666667 -0.0035000000000000005 -0.014000000000000002 -0.011666666666666667 -0.011666666666666667 -0.21466666666666667 -0.10733333333333334Z" strokeWidth="1.1667" />
                <path fill="currentColor" d="M14 2.916666666666667A1.75 1.75 0 0 1 15.750000000000002 4.666666666666667v6.302333333333334L21.207666666666668 7.816666666666667a1.75 1.75 0 0 1 1.75 3.031L17.5 14l5.457666666666667 3.151166666666667a1.75 1.75 0 0 1 -1.75 3.031l-5.457666666666667 -3.1500000000000004V23.333333333333336a1.75 1.75 0 0 1 -3.5 0v-6.302333333333334L6.792333333333334 20.183333333333337a1.75 1.75 0 1 1 -1.75 -3.031L10.5 14 5.042333333333334 10.848833333333333a1.75 1.75 0 0 1 1.75 -3.031l5.457666666666667 3.1500000000000004V4.666666666666667A1.75 1.75 0 0 1 14 2.916666666666667Z" strokeWidth="1.1667" />
              </g>
            </svg>
            <p className="cta-callout-title min-w-0 font-semibold text-zinc-800 dark:text-zinc-200">
              {title}
            </p>
          </div> : null}
        <div className={`cta-callout-body text-sm leading-normal text-zinc-800 dark:text-zinc-200${title ? " cta-callout-body--indented" : ""}`}>
          {children}
        </div>
        <a href={href} target={target} rel={linkRel} onClick={handleCtaClick} data-docs-cta={trackingEvent || undefined} className="cta-callout-button inline-flex items-center justify-center gap-1 rounded-full bg-white px-3 py-1.5 text-sm font-semibold transition hover:bg-zinc-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white/50 dark:bg-white dark:hover:bg-zinc-200">
          {buttonLabel}
          <span className="cta-callout-button-arrow" aria-hidden="true">
            →
          </span>
        </a>
      </div>
    </section>;
};

Every SDK method returns three values: the **result**, the **HTTP response**, and an **error**.

Check `err` before you use the result. When `err` is `nil`, the result holds the decoded response. When `err` is set, the result is empty and you should handle the failure.

<Tip>
  Only `NewClient` panics when the base URL is missing. SDK methods return errors for API and validation failures.
</Tip>

***

## What each return value holds

```go wrap theme={"system"}
txn, resp, err := client.Transaction.Get("txn_f482a1b3-6c2d-4e89")
```

| Return value              | Contains                                                                                                        |
| :------------------------ | :-------------------------------------------------------------------------------------------------------------- |
| Result (`txn`)            | Decoded success body. Zero or `nil` when `err` is set.                                                          |
| `*http.Response` (`resp`) | HTTP status, headers, and metadata. `nil` when validation fails before a request is sent.                       |
| `error` (`err`)           | Core HTTP failure (`*ApiErrorResponse`), client-side validation error, JSON decode error, or transport failure. |

After you confirm `err == nil`, use the result and optionally log `resp.StatusCode`.

***

## Core error types

When Core rejects a request, the SDK wraps the failure in `*blnkgo.ApiErrorResponse`. Use `errors.As` to read structured fields instead of parsing message text.

```go wrap theme={"system"}
type ApiErrorDetail struct {
	Code    string
	Message string
	Details interface{}
}

type ApiErrorResponse struct {
	Status      int
	Message     string
	LegacyError string
	ErrorDetail *ApiErrorDetail
	Body        []byte
}
```

| Field         | Description                                                                         |
| :------------ | :---------------------------------------------------------------------------------- |
| `Status`      | HTTP status code from Core (for example `404`).                                     |
| `Message`     | HTTP status text (for example `"404 Not Found"`).                                   |
| `LegacyError` | Flat `"error"` string from Core when present.                                       |
| `ErrorDetail` | Structured details parsed from `error_detail`. Read `ErrorDetail.Code` for routing. |
| `Body`        | Raw JSON error payload from Core.                                                   |

The SDK also exports `blnkgo.AsApiErrorResponse(err)` as a shortcut for `errors.As`.

***

## How to handle errors

<Steps>
  <Step title="Check err">
    On every call, confirm `err` is `nil` before you use the result.

    ```go Error handling wrap theme={"system"}
    txn, resp, err := client.Transaction.Get("txn_f482a1b3-6c2d-4e89")
    if err != nil {
    	var apiErr *blnkgo.ApiErrorResponse
    	if errors.As(err, &apiErr) {
    		switch apiErr.Status {
    		case http.StatusNotFound:
    			// Check apiErr.ErrorDetail.Code (e.g. TXN_NOT_FOUND)
    		case http.StatusUnauthorized, http.StatusForbidden:
    			// Check the API key and scopes
    		default:
    			// Log apiErr.Status and apiErr.ErrorDetail.Code
    		}
    	}
    	return err
    }

    // Use txn
    ```
  </Step>

  <Step title="Read the error detail">
    Use the field that matches the failure:

    * **Core rejection:** `errors.As` matches `*ApiErrorResponse`. Read `apiErr.ErrorDetail.Code` for logic. Use `apiErr.Status` when you only need broad handling (401, 404, 409, 5xx).
    * **SDK validation:** plain `error` before any HTTP call. Read `err.Error()` and fix the payload before retrying.

    See [API error codes](/advanced/error-codes) for the full list of codes Core returns and what each one means.
  </Step>

  <Step title="Handle transport failures">
    When the SDK cannot reach Core or the request times out, you get a network or timeout error from the HTTP client. Configure timeout and logging in [your SDK client](/sdks/go/start/using-the-sdk#timeouts-and-retries).
  </Step>
</Steps>

***

## What Core sends on rejection

When Core rejects a request, the response body looks like this:

```json 404 Not Found wrap theme={"system"}
{
  "error": "transaction not found",
  "error_detail": {
    "code": "TXN_NOT_FOUND",
    "message": "transaction not found"
  }
}
```

The SDK maps that JSON into `ApiErrorResponse`. Read `apiErr.ErrorDetail.Code` in your app, not the message string. Message text can change between releases.

When Core returns only a flat `"error"` string with no `error_detail`, the SDK sets `ErrorDetail.Code` to `"UNKNOWN"`.

| Status         | When it happens                                          | What to do                                                              |
| :------------- | :------------------------------------------------------- | :---------------------------------------------------------------------- |
| `404`          | Resource ID or path does not exist                       | Check `apiErr.ErrorDetail.Code` (e.g. `TXN_NOT_FOUND`, `IDT_NOT_FOUND`) |
| `401` or `403` | API key, scope, or permission failure                    | Check the key, scopes, and whether the method requires the master key   |
| `409`          | Conflict (duplicate reference, lock, or in-progress job) | Retry only if the operation is safe to repeat                           |
| `400`          | Core rejected the payload                                | Fix the request body before retrying                                    |
| `5xx`          | Core or upstream failure                                 | Retry later and check Core logs                                         |

<Warning>
  Do not match exact error message strings in application logic. Prefer `apiErr.ErrorDetail.Code` for routing and `apiErr.ErrorDetail.Message` for user-facing text only.
</Warning>

***

## Client-side validation

Some methods validate input before sending a request. When validation fails, Core never receives the call.

| Return value     | Value                                                             |
| :--------------- | :---------------------------------------------------------------- |
| Result           | Zero value (`nil` for pointers)                                   |
| `*http.Response` | `nil`                                                             |
| `error`          | Validation message, e.g. `reference field must be a valid string` |

<Tip>
  Each [Core API](/reference/create-ledger) lists required fields for that call.
</Tip>

***

## Related docs

<CardGroup cols={2}>
  <Card title="API error codes" icon="book-open" href="/advanced/error-codes">
    Full list of Core error codes and what each one means.
  </Card>

  <Card title="Using the SDK" icon="code" href="/sdks/go/start/using-the-sdk">
    Timeouts, retries, and logging.
  </Card>

  <Card title="0.15.0 migration" icon="arrow-right" href="/changelog/v15-migration">
    Error codes, inflight queuing, and reconciliation changes.
  </Card>

  <Card title="Quick start" icon="rocket" href="/sdks/go/start/quick-start">
    Install the SDK and create your first transaction.
  </Card>
</CardGroup>

***

## Need help?

We are very happy to help you make the most of Blnk, regardless of whether it is your first time or you are switching from another tool.

To ask questions or discuss issues, please [contact us](mailto:support@blnkfinance.com) or [join our Discord community](https://discord.gg/7WNv94zPpx).

<CtaCallout title="Connect your ledger to Blnk Cloud" href="https://cloud.blnkfinance.com/auth/sign-up?utm_source=blnk_docs&utm_medium=documentation&utm_campaign=need-help" buttonLabel="Open Blnk Cloud" trackingEvent="clicked_cloud_signup">
  Sign up and manage your ledger with our back-office dashboard. You can invite teammates to collaborate and manage your ledger operations directly from the dashboard.
</CtaCallout>
