← Back to PRs

#21883: fix: guard against undefined snapshot.skills in applySkillEnvOverride…

by felipedamacenoteodoro open 2026-02-20 13:54 View on GitHub →
agents size: XS
Title: fix: guard against undefined snapshot.skills in applySkillEnvOverridesFromSnapshot snapshot.skills can be undefined when a session is reset during an API rate-limit cooldown, causing a TypeError crash that compounds the original rate-limit issue. Use nullish coalescing (snapshot.skills ?? []) to safely skip iteration when skills is not populated. Summary • Problem: applySkillEnvOverridesFromSnapshot crashes with TypeError: snapshot.skills is not iterable when snapshot exists but .skills is undefined • Why it matters: During API rate-limit cooldowns, incomplete snapshots cause cascading crashes that prevent session recovery • What changed: Added nullish coalescing (?? []) to the for...of loop on snapshot.skills • What did NOT change (scope boundary): No changes to snapshot creation logic, skill resolution, or any other iteration over snapshot.skills elsewhere Change Type (select all) • [x] Bug fix Scope (select all touched areas) • [x] Skills / tool execution Linked Issue/PR • None (discovered via production logs) User-visible / Behavior Changes None. Previously crashed; now silently skips skill env overrides when skills data is unavailable. Security Impact (required) • New permissions/capabilities? No • Secrets/tokens handling changed? No • New/changed network calls? No • Command/tool execution surface changed? No • Data access scope changed? No Repro + Verification Environment • OS: Ubuntu 22.04 (Linux 6.8.0-100-generic x64) • Runtime/container: Node v22.22.0 • Model/provider: anthropic/claude-opus-4-6 • Integration/channel: Telegram • Relevant config: Default OpenClaw gateway config Steps 1. Trigger API rate-limit cooldown on all providers (heavy usage or 429 responses) 2. Run /new or /reset to start a new session while providers are in cooldown 3. Snapshot is created without .skills property populated 4. applySkillEnvOverridesFromSnapshot crashes on for...of snapshot.skills Expected • Session resets gracefully, skill env overrides are skipped if unavailable Actual • TypeError: snapshot.skills is not iterable — session fails to initialize, compounding rate-limit recovery Evidence Production log from 2026-02-20T05:20:21.021Z: lane task error: lane=main durationMs=128 error="TypeError: snapshot.skills is not iterable" lane task error: lane=session:agent:main:main durationMs=135 error="TypeError: snapshot.skills is not iterable" Human Verification (required) • Verified scenarios: Confirmed the crash in production logs, verified the fix changes only the iteration guard • Edge cases checked: snapshot.skills being undefined, null, or empty array — all handled by ?? [] • What you did not verify: Could not reproduce rate-limit cooldown in test environment Compatibility / Migration • Backward compatible? Yes • Config/env changes? No • Migration needed? No Failure Recovery (if this breaks) • How to disable/revert this change quickly: Revert single line in src/agents/skills/env-overrides.ts • Files/config to restore: src/agents/skills/env-overrides.ts • Known bad symptoms reviewers should watch for: Skill env overrides silently not being applied (unlikely — only triggers when skills is already undefined) Risks and Mitigations • Risk: Masking a deeper issue where snapshot.skills should always be defined • Mitigation: This is a defensive guard only; the root cause (incomplete snapshot during rate-limit) should be investigated separately <!-- greptile_comment --> <h3>Greptile Summary</h3> Added nullish coalescing operator (`?? []`) to safely handle `undefined` `snapshot.skills` during session reset, preventing `TypeError: snapshot.skills is not iterable` crash during API rate-limit cooldowns. - The fix is minimal and defensive, only affecting the iteration guard in `applySkillEnvOverridesFromSnapshot` - Type signature correctly defines `skills` as required in `SkillSnapshot`, but runtime scenarios (deserialization, partial state during cooldowns) can produce incomplete snapshots - No other code locations iterate over `snapshot.skills` without first checking for the snapshot itself being undefined <h3>Confidence Score: 5/5</h3> - Safe to merge with no risk - Single-line defensive fix using idiomatic TypeScript nullish coalescing, matches existing pattern in codebase (line 69 checks `!snapshot`), addresses production crash with no side effects, properly handles edge cases (undefined, null, empty array) - No files require special attention <sub>Last reviewed commit: 20da030</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs