Node SDK: Error Handling

Error Types

The SDK throws typed errors for different failure scenarios:

import { Keito, KeitoError, ValidationError, AuthenticationError, RateLimitError } from '@keito/sdk';

try {
  await keito.timeEntries.create({ /* ... */ });
} catch (err) {
  if (err instanceof ValidationError) {
    console.error(`Validation failed: ${err.message} (field: ${err.field})`);
  } else if (err instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (err instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${err.retryAfter}s`);
  } else if (err instanceof KeitoError) {
    console.error(`API error: ${err.code} — ${err.message}`);
  }
}

Error Properties

All KeitoError instances include:

Property Type Description
code string Error code (e.g., validation_error)
message string Human-readable description
status number HTTP status code
field string Field that caused the error (validation only)

Automatic Retries

The SDK automatically retries on 429 (rate limit) and 5xx (server error) responses:

const keito = new Keito({
  maxRetries: 3,       // default: 2
  retryDelay: 1000,    // default: 1000ms (exponential backoff)
});

Retries use exponential backoff. For 429 responses, the SDK respects the Retry-After header.

Disabling Retries

const keito = new Keito({
  maxRetries: 0,
});

Handling Specific Scenarios

Agent Session Cleanup

If an agent fails mid-session, clean up the running timer:

const entry = await keito.timeEntries.startTimer({
  project_id: 'prj_abc',
  task_id: 'tsk_001',
  spent_date: new Date().toISOString().split('T')[0],
  source: 'agent',
  /* ... */
});

try {
  await myAgent.run();
} catch (err) {
  // Discard the running timer
  await keito.timeEntries.delete(entry.id);
  throw err;
}

Project Not Assigned

try {
  await keito.timeEntries.create({
    project_id: 'prj_not_assigned',
    /* ... */
  });
} catch (err) {
  if (err instanceof KeitoError && err.code === 'project_not_assigned') {
    console.error('Agent user is not assigned to this project');
  }
}