> ## 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 Core error bodies, 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.

On success, the result holds the resource and `resp.StatusCode` reflects Core's HTTP status. On failure, `err` describes what went wrong. For Core HTTP errors, the SDK wraps the response in `*blnkgo.ApiErrorResponse`.

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

***

## Parse the return values

Read the error first. Use `resp.StatusCode` for logging and metrics after you confirm success.

```go theme={"system"}
txn, resp, err := client.Transaction.Get("txn_f482a1b3-6c2d-4e89")
if err != nil {
	var apiErr *blnkgo.ApiErrorResponse
	if errors.As(err, &apiErr) {
		fmt.Printf("API error %d: %s\n", apiErr.Status, string(apiErr.Body))
	}
	return err
}

// Use txn
fmt.Printf("HTTP status: %d\n", resp.StatusCode)
```

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

***

## How to handle errors

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

    ```go Error handling 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:
    			// Resource not found
    		case http.StatusUnauthorized, http.StatusForbidden:
    			// Auth or scope failure: check the API key
    		default: // Log apiErr.Status and string(apiErr.Body)
    		}
    	}
    	return err
    }

    // Use txn
    ```
  </Step>

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

    * **Core rejection** (`errors.As` matches `*ApiErrorResponse`): read `apiErr.Status` and parse `apiErr.Body` as JSON when you need structured fields such as `error_detail.code`.
    * **SDK validation** (plain `error` before any HTTP call): read `err.Error()` and fix the payload before retrying.

    Route on `apiErr.Status` when you do not need code-level logic (401, 404, 409, 5xx).
  </Step>

  <Step title="Configure transport handling">
    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) to investigate these failures.
  </Step>
</Steps>

***

## Core errors

When Core rejects a request, the SDK wraps the failure in `*ApiErrorResponse`. It sets `Status` to Core's HTTP status, `Message` to the HTTP status text, and `Body` to Core's raw JSON error payload.

On Core 0.15.0 and later, a rejected request looks like this:

```go 404 Not Found expandable theme={"system"}
txn, resp, err := client.Transaction.Get("txn_missing")
if err != nil {
	var apiErr *blnkgo.ApiErrorResponse
	if errors.As(err, &apiErr) {
		// apiErr:
		//   Status:  404
		//   Message: "404 Not Found"
		//   Body:    []byte(`{"error":"transaction not found","error_detail":{"code":"TXN_NOT_FOUND","message":"transaction not found","details":{}}}`)
		//
		// Parse error_detail.code from string(apiErr.Body) when you need code-level routing.
	}
}
```

Parse `error_detail.code` from `apiErr.Body` when you need code-level routing. Treat message strings as display text; Core may change wording between releases. On older Core versions, `error_detail.code` may be absent from the body.

| Status         | When it happens                                          | What to do                                                                                          |
| :------------- | :------------------------------------------------------- | :-------------------------------------------------------------------------------------------------- |
| `404`          | Resource ID or path does not exist                       | Parse `error_detail.code` from `apiErr.Body` when available (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. Message text can change. Prefer `error_detail.code` from `apiErr.Body` for routing and message strings for user-facing text only. See the [0.15.0 migration guide](/changelog/v15-migration) and [API error codes](/advanced/error-codes).
</Warning>

***

## Client-side validation

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

| Field            | 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>

***

## Transport failures

When the SDK cannot reach Core or the request times out, you get a network or timeout error from `http.Client`. Configure timeout and logging in [your SDK client](/sdks/go/start/using-the-sdk#timeouts-and-retries) to investigate these failures.

When debugging transport failures, log the error, the endpoint you called, and any HTTP status returned before the failure.

***

## Related docs

<CardGroup cols={2}>
  <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>

  <Card title="Changelog" icon="scroll-text" href="/changelog/blnk-go">
    Go SDK releases and version history.
  </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>
