SDK

SDK errors

Every error the SDK throws is an OortError subclass. Branch on code first, then on reason, and retry only what says retryable.

Handling an Oort errorA call such as recall or observe throws an OortError carrying a code, a reason and a fix. Your handler retries it when retryable is true, runs the fix, or throws it on.A callrecall, observe, ...OortErrorcode, reason, fixYour handlerretry, fix or rethrow

What an error carries

FieldWhat it is
codeOne of ten codes, the same the CLI's --json output uses.
reasonA finer, stable string, when there is one.
fixA runnable oort command that fixes it, or null.
retryableTrue when the same call can succeed later.
retryAfterSeconds to wait, when Oort Cloud sent Retry-After.
statusThe HTTP status, for an Oort Cloud refusal.
messageOne line for people. It names fields, never their values, and never carries a key.

OortNeedsKeyError also has role (embed, rerank, decide or write) and envVar, the environment variable that would supply the key. A model vendor's own error is reported by its class name only.

Codes and reasons

OortUsageError
codeusage
Typical reasoninvalid-argument, principal-required, self-not-derivable, user-missing, closed, embedder-mismatch (fix oort reembed), bad-request, too-large
OortNotFoundError
codenot-found
Typical reasonnone
OortAmbiguousIdError
codeambiguous-id
Typical reasonnone
OortNeedsKeyError
codeneeds-key
Typical reasonmissing-key (fix oort models pull or oort keys set)
OortNeedsLoginError
codeneeds-login
Typical reasonno-key, key-rejected (fix oort login)
OortNeedsConfirmationError
codeneeds-confirmation
Typical reasonpreview-required, findings-unacknowledged
OortCloudOnlyError
codecloud-only
Typical reasonhive-level, or forget with everywhere in local mode
OortNetworkError
codenetwork
Typical reasonunreachable, timeout, busy. Always retryable.
OortRefusedError
coderefused
Typical reasonscope-denied, forbidden, star-in-cloud, star-with-user, local-only, experts-not-listed, not-an-expert, daily-limit, cap-unavailable (retryable), expert-only, not-current, payment-required, not-enabled, hive-not-enabled, rate-limit (retryable), migration-required (fix oort doctor)
OortInternalError
codeinternal
Typical reasonstore-busy (retryable), else none

New reason strings may appear in any release, so branch on code first and treat an unknown reason like its code.

Handle them

Retry what is retryable, waiting retryAfter when it is set. Then branch on code, and show reason and fix:

TypeScript
import { createOort, OortError } from 'oortmem';

/** Retries what Oort marks `retryable`, waiting `retryAfter` seconds when the service sent it. */
async function withRetry<T>(fn: () => Promise<T>, tries = 3): Promise<T> {
  for (let attempt = 1; ; attempt++) {
    try {
      return await fn();
    } catch (e) {
      if (!(e instanceof OortError) || !e.retryable || attempt >= tries) throw e;
      await new Promise((done) => setTimeout(done, (e.retryAfter ?? attempt) * 1000));
    }
  }
}

try {
  await using oort = await createOort({ mode: 'cloud', keySources: ['env'] });
  const r = await withRetry(() =>
    oort.observe({ user: 'Our staging database runs on port 6543.', assistant: 'Noted.' }),
  );
  console.log('saved:', r.outcome);
} catch (e) {
  if (!(e instanceof OortError)) throw e;
  // Branch on `code` first: new `reason` strings may appear in any release.
  switch (e.code) {
    case 'needs-login':
      console.error(`No usable Oort key (${e.reason}). Fix: ${e.fix}`);
      break;
    case 'refused':
      console.error(`Refused (${e.reason}): ${e.message}`);
      break;
    case 'network':
      console.error(`Oort Cloud is unreachable (${e.reason}); try again later.`);
      break;
    default:
      throw e;
  }
}

Retry

These are retryable, and nothing else is:

  • Every OortNetworkError: unreachable, timeout and busy.
  • rate-limit and cap-unavailable (OortRefusedError).
  • store-busy (OortInternalError): another process held the local store's lock.

Wait retryAfter seconds when it is set. In cloud mode, retry observe with the same turnRef: Oort Cloud saves the turn once and answers duplicate: true. Local mode does not deduplicate, so a retried observe may write twice. The serverless example passes the request id as turnRef.

An aborted signal stops the SDK waiting and rejects with the signal's reason. Work already sent (cloud) or started (local) may still land, so retry it with the same turnRef.

Limits

Anything over a limit throws OortUsageError before any I/O. The error names the field, never its value.

InputLimit
recall query2,048 UTF-8 bytes
recall limit1 to 50
observe turn128 KiB in all (the engine keeps 32 KiB of text after scrubbing)
tools summaries in a turnTruncated to 16 × 512 bytes, never refused
turnRef128 characters
remember5 facts of at most 500 characters
recent limit1 to 100
Judgment fieldsAs oort judge record: subject 500 characters, reason 2,000

Every method and its result is in the API reference.