Skip to content

feat(ruby): map core errors to typed exception classes - #1455

Open
ya-luotao wants to merge 2 commits into
superradcompany:mainfrom
ya-luotao:ruby-error-classes
Open

feat(ruby): map core errors to typed exception classes#1455
ya-luotao wants to merge 2 commits into
superradcompany:mainfrom
ya-luotao:ruby-error-classes

Conversation

@ya-luotao

@ya-luotao ya-luotao commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

TL;DR

The Ruby SDK now raises typed Microsandbox::Error subclasses (with stable #code strings) that mirror the Python SDK, so callers can rescue specific failures instead of matching message text.

Description

  • Purely additive. Every error reported by a sandbox, image, volume, snapshot, or backend operation is still a Microsandbox::Error, so existing rescue Microsandbox::Error code keeps catching all of them. Argument validation is unchanged and outside that guarantee: unknown keywords and wrongly typed values keep raising ArgumentError / TypeError before any operation runs.
  • New lib/microsandbox/errors.rb reopens the natively defined Microsandbox::Error to add Error.code / Error#code ("microsandbox-error") and defines a flat table of direct subclasses via a private define_error(name, code) factory. UnsupportedError gains #operation / #hint readers.
  • Class names and codes mirror sdk/python/microsandbox/errors.py exactly: InvalidConfigError, NoDefaultCommandError, CloudHttpError, SandboxNotFoundError, SandboxNotRunningError, SandboxAlreadyExistsError, SandboxStillRunningError, ExecTimeoutError, ExecFailedError, FilesystemError, PathNotFoundError, VolumeNotFoundError, ImageNotFoundError, ImageInUseError, ImagePullFailedError, NetworkPolicyError, SecretViolationError, TlsError, IoError, MetricsDisabledError, MetricsUnavailableError, UnsupportedOperationError, UnsupportedError, SnapshotMigrationError.
  • Following the Go SDK's finer per-variant coverage (the Ruby SDK wires the Snapshot and Volume APIs), it also defines SnapshotNotFoundError, SnapshotAlreadyExistsError, SnapshotSandboxRunningError, SnapshotImageMissingError, SnapshotIntegrityError, and VolumeAlreadyExistsError.
  • Native mapping (ext/microsandbox/src/lib.rs, new "Core error mapping" section): core_error matches the MicrosandboxError variant to a class and looks it up on the Microsandbox module, falling back to Error (then RuntimeError) if a constant is missing. run(), the backend-selection helpers, and the network: policy builder (whose BuildError is converted through core's From impl into NetworkBuilder) all use it, so the old native_error helper is gone.
  • Variant to class: InvalidConfigInvalidConfigError; NoDefaultCommandNoDefaultCommandError; CloudHttpCloudHttpError; SandboxNotFound / SandboxNotRunning / SandboxAlreadyExists / SandboxStillRunning → the matching Sandbox*Error; ExecTimeoutExecTimeoutError; ExecFailedExecFailedError (Python defines this class but does not wire the variant; Ruby does); SandboxFsOpsFilesystemError; VolumeNotFound / VolumeAlreadyExistsVolume*Error; ImageNotFound / ImageInUseImage*Error; the five Snapshot* variants and SnapshotMigration → the matching Snapshot*Error; NetworkBuilderNetworkPolicyError; IoIoError; MetricsDisabled / MetricsUnavailableMetrics*Error; AgentClient(UnsupportedOperation)UnsupportedOperationError; UnsupportedUnsupportedError.
  • Unmapped variants (Http, Database, Runtime, BootStart, Terminal, Custom, ...) still raise Microsandbox::Error. PathNotFoundError, ImagePullFailedError, SecretViolationError, and TlsError are defined for parity but have no core variant today.
  • Unsupported { op, reason } renders the Ruby API name, as the Python bridge renders the Python one: sandbox.create is not supported by this backend: the replace option is not accepted here, with error.operation == "sandbox.create" and error.hint == "the replace option is not accepted here".
  • README gains an "Errors" section (base-class guarantee, grouped class list, #code, UnsupportedError attributes) and the supported-surface paragraph mentions typed errors.
  • Tests: unit tests check the class set and flat hierarchy, unique kebab-case codes, InvalidConfigError for an empty sandbox name (and that rescue Microsandbox::Error still catches it), NetworkPolicyError for a malformed allowed_hosts entry, SandboxNotFoundError from Sandbox.get on a missing name, and UnsupportedError#operation / #hint through the cloud backend's request-building rejection (no network involved; the backend switch runs in a separate Ruby process so the test process keeps its backend selection). Integration tests cover ExecTimeoutError, FilesystemError, VolumeNotFoundError, and SandboxStillRunningError on real microVMs.

Test Plan

  • cd sdk/ruby/ext/microsandbox && rustup run stable cargo fmt -- --check && rustup run stable cargo clippy --profile ci -- -D warnings: clean (cargo 1.96.0).
  • cd sdk/ruby && rustup run stable rake test (unit, MSB_RUBY_INTEGRATION unset): 29 tests, 95 assertions, 0 failures, 0 errors, 11 omissions (the integration tests skipping).
  • cd sdk/ruby && MSB_RUBY_INTEGRATION=1 MSB_RUBY_TEST_IMAGE=public.ecr.aws/docker/library/alpine:latest rustup run stable rake test on an Apple Silicon host with the 0.6.14 runtime (ruby -Ilib -e 'require "microsandbox"; Microsandbox.install unless Microsandbox.installed?'): 28 tests, 116 assertions, 0 failures, 0 errors, 0 omissions.
  • ext/microsandbox/Cargo.lock is untouched by this PR.

Generated with Claude Code

https://claude.ai/code/session_01RqjuPiGZ34s5CPfayN8JN4

@greptile-apps

greptile-apps Bot commented Aug 24, 2026

Copy link
Copy Markdown

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Ruby SDK operation] --> B[Rust core operation]
    B -->|Success| C[Ruby result]
    B -->|MicrosandboxError| D[core_error]
    D --> E{Mapped variant?}
    E -->|Yes| F[Typed Microsandbox::Error subclass]
    E -->|No| G[Microsandbox::Error]
    D -->|Unsupported| H[UnsupportedError with operation and hint]
Loading

Reviews (1): Last reviewed commit: "feat(ruby): map core errors to typed exc..." | Re-trigger Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0328a342d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/ruby/ext/microsandbox/src/lib.rs
Raise a `Microsandbox::Error` subclass matching the core `MicrosandboxError`
variant instead of the base class for everything. The class names and
`#code` strings mirror the Python SDK (`sdk/python/microsandbox/errors.py`),
extended with the Go SDK's per-variant coverage for snapshots, exec spawn
failures, and duplicate volumes. Variants without a dedicated class still
raise `Microsandbox::Error`, so existing `rescue Microsandbox::Error` code
keeps catching everything; argument validation keeps raising `ArgumentError`
and `TypeError`.

`lib/microsandbox/errors.rb` reopens the natively defined base class to add
`Error.code` / `Error#code` and defines the flat class table. The native
extension gains a `core_error` mapping used by `run()` and the backend
selection helpers; `Unsupported { op, reason }` renders the Ruby API name
(`sandbox.create` rather than `Sandbox::create`) and attaches
`UnsupportedError#operation` / `#hint`, as the Python bridge does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Aojf59DyiLvVeQnCy3R9ft
@greptile-apps

greptile-apps Bot commented Aug 24, 2026

Copy link
Copy Markdown

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Ruby SDK operation] --> B[Magnus native extension]
  B --> C[Rust core or backend]
  C -->|MicrosandboxError| D[Core error mapping]
  D -->|Mapped variant| E[Typed Microsandbox::Error subclass]
  D -->|Unmapped variant| F[Microsandbox::Error]
  E --> G[Ruby caller rescue]
  F --> G
Loading

Reviews (2): Last reviewed commit: "feat(ruby): map core errors to typed exc..." | Re-trigger Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fd1d67e857

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +228 to +230
// -------------------------------------------------------------------------------------------------
// Core error mapping
// -------------------------------------------------------------------------------------------------

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Put error helpers under the required Functions section

This newly added section contains free functions but uses the unqualified Core error mapping label instead of the repository-required Functions/Functions: ... organization. Rename it to an approved qualified Functions section so the extension follows the mandated Rust layout.

AGENTS.md reference: AGENTS.md:L198-L204

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Aug 28, 2026

Copy link
Copy Markdown

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Ruby SDK operation] --> B[Native extension]
  B --> C[Microsandbox core]
  C -->|MicrosandboxError variant| D[Core error mapping]
  D -->|Known variant| E[Typed Microsandbox::Error subclass]
  D -->|Unmapped variant| F[Microsandbox::Error]
  E --> G[Ruby caller rescue]
  F --> G
Loading

Reviews (3): Last reviewed commit: "Merge branch 'main' into ruby-error-clas..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant