affaan-m/ECC · error · Error

Refusing to ${action}: missing destination path.

Error message

Refusing to ${action}: missing destination path.

What it means

Every managed write/delete in the install lifecycle goes through getManagedDestination(), which requires a non-empty string destinationPath before touching the filesystem. This is the first, cheapest guard: refuse the action (copy, write, remove, uninstall, repair) when the destination is missing, undefined, or not a string.

Source

Thrown at scripts/lib/install-lifecycle.js:292

      return parseJsonLikeValue(operation[key], `${operation.kind}.${key}`);
    }
  }

  return undefined;
}

function formatJson(value) {
  return `${JSON.stringify(value, null, 2)}\n`;
}

function getManagedDestination(
  destinationPath,
  trustedRoot,
  action,
  { allowFinalSymlink = false } = {}
) {
  if (!destinationPath || typeof destinationPath !== 'string') {
    throw new Error(`Refusing to ${action}: missing destination path.`);
  }

  const canonicalRoot = assertWithinTrustedRoot(trustedRoot, trustedRoot, action);
  const resolvedDestination = path.resolve(destinationPath);
  const canonicalParent = assertWithinTrustedRoot(
    path.dirname(resolvedDestination),
    canonicalRoot,
    action
  );
  const managedPath = path.join(canonicalParent, path.basename(resolvedDestination));
  let stat = null;

  try {
    stat = fs.lstatSync(managedPath);
  } catch (error) {
    if (!error || (error.code !== 'ENOENT' && error.code !== 'ENOTDIR')) {
      throw error;
    }

View on GitHub (pinned to d8409a4b08)

Solutions

  1. Inspect the operation being executed at failure time and add the missing destinationPath
  2. Discard the mutated state and re-run a fresh ./install.sh so state is regenerated from current manifests
  3. If you call the lifecycle APIs directly, assert typeof destinationPath === 'string' && destinationPath before invoking
Defensive patterns

Strategy: validation

Validate before calling

function assertDestinationPath(operation) {
  if (!operation.destinationPath || typeof operation.destinationPath !== 'string') {
    throw new Error(`operation ${operation.kind} is missing destinationPath — regenerate install state`);
  }
}

Type guard

function hasDestinationPath(operation) {
  return typeof operation?.destinationPath === 'string' && operation.destinationPath.length > 0;
}

Try / catch

try {
  writeContainedFile(op.destinationPath, content, root, 'repair');
} catch (err) {
  if (/missing destination path/.test(err.message)) {
    // state corruption: re-run a full install instead of patching operations
  }
  throw err;
}

Prevention

When it happens

Trigger: An install-state operations[] entry with no destinationPath; calling writeContainedFile/removeContainedPath/getManagedDestination with an undefined first argument; a corrupted or truncated state file.

Common situations: Hand-editing the ECC install-state JSON and dropping a field; state written by an incompatible (older/newer) schema; programmatic callers that assume a default destination.

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@d8409a4b08 (2026-08-26). Data as JSON: /api/errors/2dbed32ec08d7be5. Report an issue: GitHub.