Skip to content

feat: descriptive error messages via IDL, not binary #60

@L0STE

Description

@L0STE

Problem

#[error_code] enums currently have no way to attach human-readable messages to error variants. Anchor solves this with #[msg("...")] attributes, but that approach embeds string literals into the on-chain binary — bloating program size for zero runtime benefit. Error messages are never read on-chain; they only matter for debugging in explorers and test output.

Proposal

Support an optional #[msg("...")] attribute on #[error_code] variants, but strip the strings at compile time so they never appear in the binary. Instead, emit them exclusively into the IDL:

#[error_code]
pub enum VaultError {
    #[msg("signer does not match vault authority")]
    Unauthorized,
    #[msg("insufficient lamports for withdrawal")]
    InsufficientFunds,
}

On-chain, this compiles to exactly what we have today — ProgramError::Custom(N) with no string data. The IDL gains an errors section that maps discriminants to names and messages:

{
  "errors": [
    { "code": 6000, "name": "Unauthorized", "msg": "signer does not match vault authority" },
    { "code": 6001, "name": "InsufficientFunds", "msg": "insufficient lamports for withdrawal" }
  ]
}

Integration

  • Explorers: Read the IDL errors section to display descriptive messages for failed transactions instead of raw Custom(6000)
  • QuasarSVM / test frameworks: Resolve ProgramError::Custom codes against the IDL to show the message in test failure output
  • CLI (quasar idl): Already generates the IDL — extend it to include the errors section

Why this is better than Anchor's approach

Anchor bakes #[msg] strings into the compiled binary via std::fmt::Display. This costs binary size on every program deploy for strings that are never used on-chain. By keeping messages IDL-only, we get the same developer experience with zero binary overhead — programs stay as small as possible.

Scope

  1. quasar-derive: Parse #[msg("...")] on #[error_code] variants, discard the strings during macro expansion (no codegen change)
  2. quasar idl: Extract #[msg] strings and emit them in the IDL errors array
  3. QuasarSVM test runner: Resolve error codes against the IDL for readable test output
  4. CLI templates: Update template add-error to show #[msg] in the generated scaffold

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions