affaan-m/ECC · error
Refusing to : missing destination path.
Error message
Refusing to ${action}: missing destination path. What it means
assertWithinTrustedRoot() is a fail-closed path-containment guard: it verifies a target path is inside a trusted install root before allowing a write/repair operation. Its first check rejects a target that is missing, not a string, or empty, with this error naming the intended action. The library refuses to proceed rather than guessing a destination for a filesystem mutation.
Solutions
- Pass the fully resolved destination string as the first argument; log the value just before the call to see why it is empty.
- Fix the upstream path construction (missing config key, undefined variable, wrong join order) so a real path is produced.
- Check the action argument in the message ('write', 'repair', ...) to identify which call site sent the empty target.
- Add an explicit early check that the destination is a non-empty string with a domain-specific message before invoking the guard.
Example fix
// before
const target = cfg.install?.target; // undefined
assertWithinTrustedRoot(target, root, 'write');
// after
const target = cfg.install?.target;
if (!target) throw new Error('install.target is not configured');
assertWithinTrustedRoot(target, root, 'write'); Defensive patterns
Strategy: validation
Validate before calling
if (typeof target !== 'string' || target.length === 0) {
throw new Error(`Destination path not resolved for action '${action}': ${JSON.stringify(target)}`);
}
assertWithinTrustedRoot(target, root, action); Type guard
function isNonEmptyPath(v) {
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try {
const real = assertWithinTrustedRoot(target, root, 'write');
} catch (e) {
if (/missing destination path/.test(e.message)) {
console.error('Destination construction failed; check the config field feeding the target.');
} else throw e;
} Prevention
- Compute destination paths before invoking containment guards, not inside them.
- Validate config-driven path fields at config load time.
- Log path values once during setup to catch undefined/empty joins early.
- Use a single path-building helper so a missing segment fails in one obvious place.
When it happens
Trigger: Calling assertWithinTrustedRoot(''), assertWithinTrustedRoot(undefined), assertWithinTrustedRoot(null), or a non-string at the target slot — usually via helpers like validatedNext/canonicalRoot when the computed destination path resolved to nothing (failed path join, missing config field, empty variable).
Common situations: Install/repair scripts where a config key holding the destination is blank; path.join producing '' because a segment was undefined; refactors renaming a config field so the old lookup returns undefined; calling the guard before the destination is actually computed.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Unsafe state-store path
- Unsafe state-store path
- all overlays must be readable local files
- all takes must be readable local files
- artifact path must stay beneath output root
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/2e84ef5bc4f5a6cd.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/path-safety.js:87
function isWithinRoot(target, root) {
if (!root) {
return false;
}
try {
return resolveContainment(target, root).contained;
} catch {
return false;
}
}
/**
* Fail-closed guard: throw unless `target` is contained within `root`.
* Returns the canonicalized target path on success.
*/
function assertWithinTrustedRoot(target, root, action = 'write') {
if (!target || typeof target !== 'string') {
throw new Error(`Refusing to ${action}: missing destination path.`);
}
if (!root) {
throw new Error(`Refusing to ${action} '${target}': no trusted install root resolved.`);
}
let containment;
try {
containment = resolveContainment(target, root);
} catch {
containment = null;
}
if (!containment || !containment.contained) {
throw new Error(`Refusing to ${action} outside the install root: '${target}' is not within '${root}'.`);
}
return containment.realTarget;
}
module.exports = {View on GitHub (pinned to 8321021c54)