You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In packages/errors/src/causes/index.ts:30, the function-scope variable instance is used as the local name for what is actually a narrowed ErrorInstance:
constcauses=(error: unknown): Error[]=>{if(error==null){return[];}// Get the causes array from the errorconstinstance=errorasErrorInstance;
Rule 0005 (Named Algorithms and Independent Data Structures) treats project-internal diminutives — names that train the reader to translate every line — as a tax. instance is a JavaScript keyword-adjacent word that does not name a concept; in this function it is the receiver of an unsafe cast. The function is 13 lines long; the name carries no domain meaning.
Located in:
packages/errors/src/causes/index.ts:30, 36, 38
Problems with current implementation:
instance is not a domain concept; it is a JavaScript-shape term. The function deals with errors, not instances.
The reader has to remember that instance means "the error we just cast" rather than "an instance of something" — the cast is the only thing giving the name meaning.
The neighbouring parameter is named error; instance next to it is redundant.
Proposed State
After refactoring, the variable is renamed to errorInstance (full form, no truncation) and the function uses an early-return that makes the narrowing explicit:
The shape of the cast is preserved (as ErrorInstance was unsound — the new code replaces it with a structural guard, which is the rule 0004 / 0008 cooperative fix).
Expected improvements:
Rule 0005 compliance: no project-internal diminutives.
Rule 0004 compliance: the runtime guard names its scenario ("causes is an array") instead of relying on a cast.
Rule 0008 compliance: the cast at the call site is removed.
The function reads top-down (rule 0007): each branch is a name, no cast survives the null guard.
Motivation
This refactoring is needed because:
The variable is a diminutive that a reader has to mentally expand on every read.
The function is exported as part of the public API (causes); the name carries weight for consumers who skim the source.
Combining the rename with the structural-guard refactor kills three birds (0005, 0004, 0008) in one pass.
Triggers for this work:
Technical debt accumulation
Maintainability concerns
Risks
Potential risks:
Risk 1: A consumer relies on causes() returning [] for inputs that are not null but also don't have a causes array. — Mitigation: the current code does instance as ErrorInstance then checks Array.isArray(instance.causes). If the cast succeeds (the input has a causes property of any shape), the function returns that shape. The new code preserves the same behaviour through a structural check.
Risk 2: The error.causes property does not exist on native Error instances. — Mitigation: the early return if (!('causes' in error) || !Array.isArray(error.causes)) return []; covers this; native errors return [] as before.
Migration Plan
Migration approach:
Replace the cast + Array.isArray check with a single structural guard.
Rename instance to errorInstance (or remove the local entirely by inlining the structural check, which the early-return shape makes natural).
Update tests if they assert on the cast's runtime behaviour.
Rollback plan: revert the PR. The change is local.
Backward Compatibility
This refactoring maintains full backward compatibility
Scope
Files/Folders affected:
packages/errors/src/causes/index.ts (the function body)
packages/errors/tests/ (if any test exercises the cast path)
Component(s) Affected
Multiple Components
Note: the component_affected dropdown is calibrated for a web template project. The actual affected component is packages/errors.
Priority
p0: Critical - Blocking major work or causing bugs
Current State
In
packages/errors/src/causes/index.ts:30, the function-scope variableinstanceis used as the local name for what is actually a narrowedErrorInstance:Rule 0005 (Named Algorithms and Independent Data Structures) treats project-internal diminutives — names that train the reader to translate every line — as a tax.
instanceis a JavaScript keyword-adjacent word that does not name a concept; in this function it is the receiver of an unsafe cast. The function is 13 lines long; the name carries no domain meaning.Located in:
packages/errors/src/causes/index.ts:30, 36, 38Problems with current implementation:
instanceis not a domain concept; it is a JavaScript-shape term. The function deals with errors, not instances.instancemeans "the error we just cast" rather than "an instance of something" — the cast is the only thing giving the name meaning.error;instancenext to it is redundant.Proposed State
After refactoring, the variable is renamed to
errorInstance(full form, no truncation) and the function uses an early-return that makes the narrowing explicit:The shape of the cast is preserved (
as ErrorInstancewas unsound — the new code replaces it with a structural guard, which is the rule 0004 / 0008 cooperative fix).Expected improvements:
causesis an array") instead of relying on a cast.Motivation
This refactoring is needed because:
causes); the name carries weight for consumers who skim the source.Triggers for this work:
Risks
Potential risks:
causes()returning[]for inputs that are notnullbut also don't have acausesarray. — Mitigation: the current code doesinstance as ErrorInstancethen checksArray.isArray(instance.causes). If the cast succeeds (the input has acausesproperty of any shape), the function returns that shape. The new code preserves the same behaviour through a structural check.error.causesproperty does not exist on nativeErrorinstances. — Mitigation: the early returnif (!('causes' in error) || !Array.isArray(error.causes)) return [];covers this; native errors return[]as before.Migration Plan
Migration approach:
Array.isArraycheck with a single structural guard.instancetoerrorInstance(or remove the local entirely by inlining the structural check, which the early-return shape makes natural).Rollback plan: revert the PR. The change is local.
Backward Compatibility
Scope
Files/Folders affected:
packages/errors/src/causes/index.ts(the function body)packages/errors/tests/(if any test exercises the cast path)Component(s) Affected
Note: the
component_affecteddropdown is calibrated for a web template project. The actual affected component ispackages/errors.Priority
Estimated Effort
Test Coverage Requirements
Testing Approach
Verification steps:
pnpm --filter @deessejs/errors test:runpnpm --filter @deessejs/errors type-checkRelated Issues / Pull Requests
packages/errors/src/against rules 0001-0016, August 2026.docs/engineering/architecture/rules/0005-named-algorithms-and-independent-data-structures.md.docs/engineering/architecture/rules/0004-no-speculative-defences.md.docs/engineering/architecture/rules/0008-no-chained-type-assertions.md.Relevant Documentation
docs/engineering/architecture/rules/0005-named-algorithms-and-independent-data-structures.mdPre-Submission Checklist