NOUKAI

Exceptions

SDK exception types and error codes.

Exception Hierarchy

All SDK exceptions inherit from NoukaiError:

NoukaiError (base)
├── APIConnectionError
├── APITimeoutError
├── AuthenticationError
├── PermissionDeniedError
├── FlowNotFoundError
├── InsufficientCreditsError
├── RateLimitError
├── FlowExecutionError
└── ToolCallLimitError

NoukaiError

Base class for all Noukai SDK exceptions.

Attributes:

  • code (string): Error code for programmatic dispatch
  • message (string): Human-readable error message
  • statusCode (number | undefined): HTTP status code (if applicable)

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof NoukaiError) {
    console.log(`Code: ${e.code}`);
    console.log(`Message: ${e.message}`);
  }
}

AuthenticationError

API key is invalid, missing, or expired.

Code: authentication_error
HTTP Status: 401

Causes:

  • No API key provided
  • Invalid API key prefix (not starting with nk_)
  • API key is revoked or expired

Example:

try {
  const noukai = new Noukai({ apiKey: "invalid_key" });
} catch (e) {
  if (e instanceof AuthenticationError) {
    console.log("Check your API key at https://console.noukai.xyz");
  }
}

PermissionDeniedError

User lacks permission to access the flow.

Code: permission_denied
HTTP Status: 403

Causes:

  • Flow is private and user doesn't have access
  • User role doesn't allow flow execution

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof PermissionDeniedError) {
    console.log("You don't have access to this flow");
  }
}

FlowNotFoundError

Flow doesn't exist or was deleted.

Code: flow_not_found
HTTP Status: 404

Causes:

  • Flow slug is incorrect
  • Flow was deleted
  • Flow is in a different organization/project

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof FlowNotFoundError) {
    console.log("Check flow slug at https://console.noukai.xyz/flows");
  }
}

InsufficientCreditsError

Account has no remaining credits.

Code: insufficient_credits
HTTP Status: 402

Causes:

  • Account balance is zero
  • Credits expired

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof InsufficientCreditsError) {
    console.log("Add credits at https://console.noukai.xyz/billing");
  }
}

RateLimitError

Request rate limit exceeded.

Code: rate_limit_exceeded
HTTP Status: 429

Causes:

  • Too many requests in a short time
  • Concurrent request limit exceeded

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof RateLimitError) {
    console.log("Rate limited. Backing off...");
    await new Promise((r) => setTimeout(r, 60000));
    // Retry
  }
}

APITimeoutError

Request timed out.

Code: api_timeout
HTTP Status: 504

Causes:

  • Network latency
  • Noukai service slow
  • Request timeout exceeded

Note: The SDK automatically retries once on timeout. This exception means both attempts failed.

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof APITimeoutError) {
    console.log("Request timed out. Please retry.");
  }
}

APIConnectionError

Connection to Noukai failed.

Code: api_connection
HTTP Status: N/A

Causes:

  • Network unreachable
  • DNS resolution failed
  • TLS handshake failed

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof APIConnectionError) {
    console.log("Network error. Check your internet connection.");
  }
}

FlowExecutionError

Flow execution failed.

Code: flow_execution_error
HTTP Status: 500

Causes:

  • LLM provider error
  • Step execution error
  • Invalid flow configuration

Attributes:

  • details (object | undefined): Additional error details from the flow

Example:

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof FlowExecutionError) {
    console.log(`Flow failed: ${e.message}`);
    if ("details" in e) {
      console.log(`Details: ${e.details}`);
    }
  }
}

ToolCallLimitError

Tool calls exceeded retry limit.

Code: tool_call_limit
HTTP Status: N/A

Causes:

  • Tool execution failed repeatedly
  • All retries exhausted

Attributes:

  • toolCallId (string | undefined): ID of the failing tool call
  • attemptCount (number | undefined): Number of attempts made

Example:

try {
  const result = await flow.execute({
    message: "hello",
    tools: [...],
    toolHandler: handler
  });
} catch (e) {
  if (e instanceof ToolCallLimitError) {
    console.log(`Tool call failed after ${(e as any).attemptCount} attempts`);
  }
}

Error Codes Reference

ExceptionCodeHTTPWhen to handle
AuthenticationErrorauthentication_error401Check API key setup
PermissionDeniedErrorpermission_denied403User role / flow access
FlowNotFoundErrorflow_not_found404Verify flow slug
InsufficientCreditsErrorinsufficient_credits402Billing / top-up
RateLimitErrorrate_limit_exceeded429Implement backoff
APITimeoutErrorapi_timeout504Retry manually
APIConnectionErrorapi_connectionCheck network
FlowExecutionErrorflow_execution_error500Debug flow config
ToolCallLimitErrortool_call_limitFix tool handler

Error Handling Patterns

By Exception Type

import {
  FlowNotFoundError,
  InsufficientCreditsError,
  AuthenticationError,
  NoukaiError
} from "@noukai/sdk";
 
try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof FlowNotFoundError) {
    // Handle missing flow
  } else if (e instanceof InsufficientCreditsError) {
    // Handle billing
  } else if (e instanceof AuthenticationError) {
    // Handle auth
  } else if (e instanceof NoukaiError) {
    // Handle other Noukai errors
  }
}

By Error Code

try {
  const result = await flow.execute({ message: "hello" });
} catch (e) {
  if (e instanceof NoukaiError) {
    if (e.code === "flow_not_found") {
      // Handle missing flow
    } else if (e.code === "insufficient_credits") {
      // Handle billing
    } else {
      throw e;
    }
  }
}

With Retries

async function executeWithBackoff(
  flow: Flow,
  message: string,
  maxRetries = 3
): Promise<ExecuteResult> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await flow.execute({ message });
    } catch (e) {
      if (e instanceof APITimeoutError) {
        if (attempt === maxRetries - 1) {
          throw e;
        }
        const waitTime = 2 ** attempt * 1000;  // Exponential backoff
        await new Promise((r) => setTimeout(r, waitTime));
      } else {
        throw e;
      }
    }
  }
  throw new Error("Unexpected");
}

On this page