Skip to content

Diagnostics: runtime errors have no source location (at <anonymous>) — add file:line to throws #5247

Closed

Description

@proggeramlug

Context: debugging native npm-dep compilation. Several real packages fail at runtime with errors of the form "X is not a function" on perry's numeric 0-sentinel — ajv ((number).test), yargs (Bind must be called on a function), nanoid/yup (value is not a function). They're impossible to localize because perry's runtime errors carry no source location: crates/perry-runtime/src/error.rs::make_stack hardcodes "<name>: <message>\n at <anonymous>" for every error, and there's no call-stack / source-position tracking.

Goal

Give runtime errors a real source location — replace at <anonymous> with at <file>:<line>, at minimum for the call-dispatch throws (X is not a function, X is not a constructor, property-on-non-object), which is the class blocking native-compile debugging.

Suggested approach (bounded first increment)

  1. Carry a source position on the relevant throwing HIR nodes (call / method-call / member-access / new). The SWC AST has spans; AST→HIR lowering currently drops them (AOT: defer non-resolvable dynamic import() to a runtime error (shared notice + strict), like #5206 #5230 already added a byte_offset field to Expr::DynamicImport for this exact reason — follow that precedent). Set byte_offset from span.lo in lowering.
  2. Codegen passes that byte_offset (and the module id) into the dispatch/throw path so the "not a function/constructor" throw helpers (throw_type_error, js_throw_type_error_not_a_function, etc. in perry-runtime) receive it.
  3. Runtime resolves byte_offset → file:line via a per-module byte→line table built at compile time (embed a compact line-start index per compiled module), and make_stack emits at <file>:<line> when a location is available (fall back to <anonymous>).
  4. Gate the codegen location-emission behind a flag (--trace-locations, or reuse --debug-symbols) so release-build perf is unaffected; default off keeps current behavior.

Verify

  • const f: any = 5; f.test(); compiled with the flag → the thrown TypeError (and .stack) reports at <file>:<line> of the f.test() call, not <anonymous>.
  • Payoff: compile a tiny ajv consumer (compilePackages: ["*"]) with the flag and report the file:line the (number).test throw now points at — that localizes the sentinel bug for a follow-up fix.

Scope

This issue is the throw-site source location. Full V8-style multi-frame stack traces (a live call-stack with function names per frame) are a larger follow-up. Deliver the bounded increment; if even that splits, ship the runtime+error.rs location-rendering + one throw path and report what's deferred.

Impact

Unblocks debugging the entire native-compile "sentinel-0" class (ajv/yargs/nanoid/yup) and every future native-compile runtime error — turns guess-and-check into normal debugging.

Activity

  1. added
    enhancementNew capability or improvement
    toolingDeveloper tooling, CI, tests, or release infrastructure
    on Jun 16, 2026
  2. added 6 commits that reference this issue on Jun 16, 2026
  3. added 2 commits that reference this issue on Jul 18, 2026
  4. proggeramlug commented on Jul 30, 2026

    @proggeramlug
    ContributorAuthor

    Closing as completed by the merged increments in #5250, #5274, #5573, and #6597. The requested bounded --debug-symbols path now reports file:line for dynamic method-call and bare value-call TypeErrors, not-a-constructor throws, unresolved-identifier ReferenceErrors, and nullish property reads. I re-ran the four focused integration suites on current main: 11/11 tests pass, including the default-build <anonymous> fallback checks. Full multi-frame stacks remain outside this issue’s stated scope; property writes/index reads can be tracked separately if still needed.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew capability or improvementtoolingDeveloper tooling, CI, tests, or release infrastructure

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions