Skip to content

fix: guard against undefined tool output in caching and pruning#2

Closed
Sathvik-1007 wants to merge 1 commit intosdwolf4103:mainfrom
Sathvik-1007:fix/undefined-tool-output-crash
Closed

fix: guard against undefined tool output in caching and pruning#2
Sathvik-1007 wants to merge 1 commit intosdwolf4103:mainfrom
Sathvik-1007:fix/undefined-tool-output-crash

Conversation

@Sathvik-1007
Copy link
Copy Markdown

Summary

Fixes #1TypeError: undefined is not an object crash in applySmartPruning / keepLast when cached tool output has no fullOutput field.

Root Cause

hookOutput.output can be undefined for certain tool calls (e.g. MCP tools that return no output). When cached via cacheToolOutput, the fullOutput field is omitted from the JSON. On later replay, getCachedToolOutput returns an object where fullOutput is undefined, which crashes when passed to applySmartPruning.split('\n') or keepLast.length.

Changes

Two defensive guards in index.ts:

  1. Cache write (line ~1595): Nullish coalesce toolOutput ?? "" before storing, so fullOutput is always a string in the cache file. Same guard applied to extractFromToolOutput call.
  2. Cache read (line ~1639): Check cached.fullOutput is truthy before passing to applySmartPruning, skipping records with missing output instead of crashing.

Testing

Reproduced the crash by triggering tool calls that return undefined output. After the fix, pruning skips gracefully and no crash occurs.

hookOutput.output can be undefined for some tool calls. This undefined
value gets cached without a fullOutput field, and later crashes
applySmartPruning/keepLast when they call .split() or .length on it.

Two fixes:
- Nullish coalesce toolOutput to empty string before caching and extraction
- Check cached.fullOutput is truthy before passing to applySmartPruning

Fixes sdwolf4103#1
@sdwolf4103
Copy link
Copy Markdown
Owner

sdwolf4103 commented Apr 28, 2026

Thanks @Sathvik-1007 for the report and fix. This PR targets the old index.ts implementation, and the current codebase has since been refactored/released so this patch no longer applies cleanly to current main. I am closing this stale PR for now. If the same crash still appears on the current version, please open a fresh PR or issue against the latest code.

@sdwolf4103 sdwolf4103 closed this Apr 28, 2026
sdwolf4103 added a commit that referenced this pull request May 2, 2026
…nce, and validation baseline

Wave 1 — Compaction prompt improvement:
- Add three wording-reuse bullets to buildCompactionPrompt() under
  CRITICAL MEMORY RULES: do not create rephrased duplicates, reuse
  existing wording exactly when re-emitting, only emit new memories
  when the fact is new, materially corrected, or more specific.
- This attacks the root cause of zero reinforcement: compaction
  generating variant text for the same durable fact.

Wave 2 — Bug fixes:
- Bug #2: Add placeholder comment to superseded_existing branch in
  decision dedupe (unreachable until v1.5.4 numbered refs). Preserve
  as const type assertions.
- Bug #3: Add memory_migration_superseded evidence event type. Both
  P0 and quality cleanup migrations now produce evidence events for
  superseded entries. loadWorkspaceMemory appends migration evidence
  on first-load migrations only (idempotent via migration IDs). No
  historical backfill.
- Bug #4: Add documentation comment explaining that feedback identity
  key returns exact key (absorbed_identity currently impossible for
  feedback). Add test verifying this behavior.

Wave 3 — Validation baseline script:
- Add scripts/dev/validate-identity-keys.ts: read-only script that
  scans workspace memory stores, computes exact/identity key
  collisions, and reports reinforcement statistics. Baseline matches
  audit: 0 exact collisions, 0 identity collisions, 0 reinforcement
  events across 123 active memories.

Identity extension is gated on measurement: if the prompt change
produces measurable reinforcement (reinforcementCount > 0), identity
extension may be unnecessary. Decision dedupe stays exact-only
(Wave 4 deferred).
sdwolf4103 added a commit that referenced this pull request May 8, 2026
…nce, and validation baseline

Wave 1 — Compaction prompt improvement:
- Add three wording-reuse bullets to buildCompactionPrompt() under
  CRITICAL MEMORY RULES: do not create rephrased duplicates, reuse
  existing wording exactly when re-emitting, only emit new memories
  when the fact is new, materially corrected, or more specific.
- This attacks the root cause of zero reinforcement: compaction
  generating variant text for the same durable fact.

Wave 2 — Bug fixes:
- Bug #2: Add placeholder comment to superseded_existing branch in
  decision dedupe (unreachable until v1.5.4 numbered refs). Preserve
  as const type assertions.
- Bug #3: Add memory_migration_superseded evidence event type. Both
  P0 and quality cleanup migrations now produce evidence events for
  superseded entries. loadWorkspaceMemory appends migration evidence
  on first-load migrations only (idempotent via migration IDs). No
  historical backfill.
- Bug #4: Add documentation comment explaining that feedback identity
  key returns exact key (absorbed_identity currently impossible for
  feedback). Add test verifying this behavior.

Wave 3 — Validation baseline script:
- Add scripts/dev/validate-identity-keys.ts: read-only script that
  scans workspace memory stores, computes exact/identity key
  collisions, and reports reinforcement statistics. Baseline matches
  audit: 0 exact collisions, 0 identity collisions, 0 reinforcement
  events across 123 active memories.

Identity extension is gated on measurement: if the prompt change
produces measurable reinforcement (reinforcementCount > 0), identity
extension may be unnecessary. Decision dedupe stays exact-only
(Wave 4 deferred).
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.

i got this error on a long context paste.

2 participants