Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.declaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

import (
    "errors"
    "github.com/declaw-ai/declaw-go"
)
All SDK errors embed *SandboxError, which implements the error interface. Use errors.As to match specific error types, or check the base *SandboxError to catch any Declaw error.

Error hierarchy

error
└── *SandboxError
    ├── *TimeoutError
    ├── *NotFoundError
    ├── *AuthenticationError
    ├── *InvalidArgumentError
    ├── *NotEnoughSpaceError
    ├── *FileUploadError
    ├── *GitAuthError
    ├── *GitUpstreamError
    ├── *CommandExitError
    ├── *InsufficientBalanceError
    ├── *RateLimitError
    ├── *TemplateError
    └── *BuildError

SandboxError

Base error type for all Declaw errors.
type SandboxError struct {
    Message    string
    SandboxID  string
    StatusCode int
}
FieldTypeDescription
MessagestringHuman-readable error description
SandboxIDstringThe sandbox ID involved, when available
StatusCodeintHTTP status code from the API response

NotFoundError

Returned when a sandbox or resource does not exist (HTTP 404).
sbx, err := declaw.Connect(ctx, "nonexistent-id")
if err != nil {
    var nfe *declaw.NotFoundError
    if errors.As(err, &nfe) {
        fmt.Println("Sandbox not found:", nfe.Message)
    }
}

AuthenticationError

Returned when the API key is missing or invalid (HTTP 401/403).
sbx, err := declaw.Create(ctx)
if err != nil {
    var ae *declaw.AuthenticationError
    if errors.As(err, &ae) {
        fmt.Println("Invalid API key")
    }
}

InsufficientBalanceError

Returned when the account has insufficient balance (HTTP 402).
sbx, err := declaw.Create(ctx)
if err != nil {
    var ibe *declaw.InsufficientBalanceError
    if errors.As(err, &ibe) {
        fmt.Println("Top up required:", ibe.Message)
    }
}

RateLimitError

Returned when the API rate limit is exceeded (HTTP 429). Inspect RetryAfter and back off before retrying.
sbx, err := declaw.Create(ctx)
if err != nil {
    var rle *declaw.RateLimitError
    if errors.As(err, &rle) {
        fmt.Printf("Rate limited. Retry after %v\n", rle.RetryAfter)
        time.Sleep(rle.RetryAfter)
    }
}
FieldTypeDescription
RetryAftertime.DurationHow long to wait before retrying
LimitintRate limit ceiling
RemainingintRequests remaining in current window

CommandExitError

Returned when a command exits with a non-zero exit code. Contains the full stdout, stderr, and exit code. Note that Run() returns both the *CommandResult and the error, so you can inspect output even on failure.
result, err := sbx.Commands.Run(ctx, "python3 -c \"raise ValueError('oops')\"")
if err != nil {
    var exitErr *declaw.CommandExitError
    if errors.As(err, &exitErr) {
        fmt.Printf("Exit code: %d\n", exitErr.ExitCode)
        fmt.Printf("Stderr: %s\n", exitErr.Stderr)
    }
}
FieldTypeDescription
ExitCodeintThe process exit code
StdoutstringCaptured standard output
StderrstringCaptured standard error

TimeoutError

Returned when an operation exceeds its configured timeout (HTTP 408).

InvalidArgumentError

Returned when invalid arguments are passed to an API call (HTTP 422).

NotEnoughSpaceError

Returned when the sandbox filesystem is full (HTTP 507).

TemplateError / BuildError

Returned on template build or retrieval errors.

Catching all Declaw errors

sbx, err := declaw.Create(ctx)
if err != nil {
    var se *declaw.SandboxError
    if errors.As(err, &se) {
        fmt.Printf("Declaw error (HTTP %d): %s\n", se.StatusCode, se.Message)
        if se.SandboxID != "" {
            fmt.Println("Sandbox ID:", se.SandboxID)
        }
    }
}

Retry patterns

Simple retry with backoff

func runWithRetry(ctx context.Context, sbx *declaw.Sandbox, cmd string, retries int) (string, error) {
    delay := time.Second
    for attempt := 0; attempt < retries; attempt++ {
        result, err := sbx.Commands.Run(ctx, cmd,
            declaw.WithRunTimeout(30*time.Second),
        )
        if err == nil {
            return result.Stdout, nil
        }
        // Don't retry deterministic failures
        var exitErr *declaw.CommandExitError
        if errors.As(err, &exitErr) {
            return "", err // non-zero exit won't improve on retry
        }
        var ae *declaw.AuthenticationError
        if errors.As(err, &ae) {
            return "", err
        }
        var nfe *declaw.NotFoundError
        if errors.As(err, &nfe) {
            return "", err
        }
        if attempt < retries-1 {
            time.Sleep(delay)
            delay *= 2
        }
    }
    return "", fmt.Errorf("command failed after %d retries", retries)
}

Handle rate limits

func createWithRateLimit(ctx context.Context) (*declaw.Sandbox, error) {
    for {
        sbx, err := declaw.Create(ctx, declaw.WithTimeout(300))
        if err == nil {
            return sbx, nil
        }
        var rle *declaw.RateLimitError
        if errors.As(err, &rle) && rle.RetryAfter > 0 {
            time.Sleep(rle.RetryAfter)
            continue
        }
        return nil, err
    }
}

Handle non-zero exit codes

result, err := sbx.Commands.Run(ctx, "python3 risky_script.py")
if err != nil {
    var exitErr *declaw.CommandExitError
    if errors.As(err, &exitErr) {
        fmt.Printf("Script failed (exit %d)\n", exitErr.ExitCode)
        fmt.Printf("Stderr: %s\n", exitErr.Stderr)
        // result is still available
        fmt.Printf("Stdout: %s\n", result.Stdout)
    } else {
        log.Fatal(err) // network or other error
    }
}