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

  1. Pass the fully resolved destination string as the first argument; log the value just before the call to see why it is empty.
  2. Fix the upstream path construction (missing config key, undefined variable, wrong join order) so a real path is produced.
  3. Check the action argument in the message ('write', 'repair', ...) to identify which call site sent the empty target.
  4. 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

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


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)