Skip to content
19 changes: 19 additions & 0 deletions reference/configuration/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,27 @@ threads:

Snapshots can be large (often a sizable fraction of the heap limit) and writing them blocks the thread briefly β€” leave disabled for normal operation and enable only when investigating an out-of-memory pattern.

## Source Maps in Stack Traces

<VersionBadge type="changed" version="v5.4.0" />

Stack traces from Harper's core point at its compiled JavaScript under `dist/`. To map them back to the TypeScript sources, enable source maps with the Node.js `--enable-source-maps` flag, set through `NODE_OPTIONS`:

```bash
NODE_OPTIONS=--enable-source-maps harper

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If most people are running Harper on Fabric, how do they enable it? NODE_OPTIONS is not a great example for that use case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good question. On Fabric clusters that Harper hosts there is no way to turn them on today:

  • NODE_OPTIONS: users don't control the process environment, and I found no Fabric control (central-manager, host-manager, studio) that sets it.
  • threads.v8Flags: --enable-source-maps is a Node.js flag, not a V8 flag, so it can't be passed this way.

What this costs a Fabric user is smaller than it looks. Application code on the default vm-current-context loader was never source-mapped. Harper strips TypeScript types there without moving code, so those stack traces are unchanged. What stays unmapped is frames from Harper's core and from npm packages Harper loads natively. The section now says this (debugging.md), and the release note limits NODE_OPTIONS to environments you control.

If we want Fabric users to have a way in, a small core change would do it: a Harper config key that makes the main thread call process.setSourceMapsEnabled(true) at startup. Workers already inherit that (manageThreads.js passes --enable-source-maps whenever process.sourceMapsEnabled is true). I left this thread open in case you'd like that before this merges, or know of a Fabric env-var control I missed.

β€” Claude Opus 5.5

```

Harper passes the setting on to every worker thread (not under Bun). Source maps cost memory: Node.js keeps every loaded module's source map on every thread, several megabytes per thread.

The setting applies to modules Node.js loads itself: Harper's core, application code loaded natively (for example with `applications.moduleLoader: native`), and the npm packages that Harper loads natively (under the default `applications.dependencyLoader: auto`, every package that does not depend on Harper; see [Dependency Loading](../components/module-loading.md#dependency-loading)). Harper's VM-based loaders (`vm-current-context`, the default, as well as `vm` and `compartment`) do not apply source maps either way.

On Fabric clusters that Harper hosts, you do not set the process environment, so `NODE_OPTIONS` is not available there. Stack traces from application code on the default loader are the same either way; those from Harper's core and from natively loaded packages stay unmapped.

Before v5.4.0, source maps were always enabled.

## Related

- [Configuration Options β€” `threads`](./options.md#threads) β€” full thread configuration reference
- [Architecture Overview](../database/overview.md#architecture-overview) β€” how worker threads fit into Harper
- [Node.js Inspector documentation](https://nodejs.org/en/learn/getting-started/debugging) β€” debugger protocol details
- [Node.js `--enable-source-maps`](https://nodejs.org/api/cli.html#--enable-source-maps) β€” how Node.js applies source maps to stack traces
2 changes: 1 addition & 1 deletion reference/configuration/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,6 @@ Built-in plugins (REST, HTTP, operations API, etc.) and the core database are un
## See Also

- [Configuration Options](./options.md) β€” complete reference for every `harper-config.yaml` key
- [Worker Thread Debugging](./debugging.md) β€” attaching Node.js inspector to Harper's worker threads
- [Worker Thread Debugging](./debugging.md) β€” attaching Node.js inspector to Harper's worker threads, and enabling source maps in stack traces
- [Storage Tuning](../database/storage-tuning.md) β€” production tuning of `storage.*` options
- [Logging Configuration](../logging/configuration.md) β€” main and per-subsystem log settings
8 changes: 8 additions & 0 deletions release-notes/v5-lincoln/5.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ The agent records the usage of each model call on its session, and `get_agent_se

A `models.generative` entry can now declare `pricing: { inputPerMtok, outputPerMtok }`, what you pay in USD per million prompt and completion tokens. Harper ships no prices of its own. Each `generate()` call is priced at the rates of the entry that served it, a fallback included, and the result carries `costUsd` when that entry is priced and the provider reported both token counts. With `toolMode: 'auto'` it covers the final round, and streaming calls are not priced. This makes `maxCostUsd` work on `toolMode: 'auto'` calls; before, it had no prices behind it and never tripped. A `toolMode: 'auto'` round that leaves `maxCostUsd` or `maxToolTokens` unmeasurable, because the entry is unpriced or the provider reported no token counts, now stops the call with the budget error (429) instead of warning once and continuing, so set `pricing` on entries you cap by cost. See [Pricing](/reference/v5/models/overview#pricing).

## Memory

### Smaller Per-Thread Baseline

An idle Harper thread now uses roughly 40% less JavaScript heap (about 58 MB down to 35 MB in a default install, before any application code loads). Harper's compiled code is smaller in memory, and several dependencies used only by specific features (LMDB storage, certificate revocation checks, certificate generation, `system_information`) now load when that feature is first used.

Source maps are no longer enabled by default, so stack traces from Harper's core point at its compiled JavaScript. If you control the process environment (not on Fabric clusters that Harper hosts), set `NODE_OPTIONS=--enable-source-maps` to map them back to the TypeScript sources. See [Source Maps in Stack Traces](/reference/v5/configuration/debugging#source-maps-in-stack-traces).

## Component Deploys

### Certifying a Release in a Canary Worker
Expand Down
Loading