affaan-m/ECC · error

invalid qualification configuration

Error message

invalid qualification configuration

What it means

Thrown at scripts/ito.js:132 inside the try block of validateNodeQualificationArgs when the resolved config directory exists but is not a directory, OR when sixtytwo.yaml inside it is not a regular file. IMPORTANT: this throw is effectively UNREACHABLE as a user-facing message — it is thrown inside a try{} whose catch{} (ito.js:134-138) has no parameter and unconditionally re-throws error 102's message instead. Any user who triggers the condition at line 128-131 will actually see the error-102 text. This is a latent bug: the discriminating message at line 132 is dead code.

Source

Thrown at scripts/ito.js:132

      "Live node qualification requires --live-sixtytwo exactly once before any process is started."
    );
  }
  requiredOptionValue(args, "--cluster");
  const nodes = requiredOptionValue(args, "--nodes");
  if (!nodes.split(",").every((node) => node.trim().length > 0)) {
    throw new Error("--nodes must explicitly list one or more non-empty nodes.");
  }
  const configDirectory = requiredOptionValue(args, "--config-dir");
  if (!path.isAbsolute(configDirectory)) {
    throw new Error("--config-dir must be an existing absolute directory.");
  }
  try {
    const resolved = fs.realpathSync.native(configDirectory);
    if (
      !fs.statSync(resolved).isDirectory()
      || !fs.statSync(path.join(resolved, "sixtytwo.yaml")).isFile()
    ) {
      throw new Error("invalid qualification configuration");
    }
  } catch {
    throw new Error(
      "--config-dir must exist and contain a regular sixtytwo.yaml before any process is started."
    );
  }
}

function parseArgs(argv, environment = process.env) {
  const args = [...argv];
  if (
    args.length === 0
    || args.includes("--help")
    || args.includes("-h")
  ) {
    return Object.freeze({ help: true, invocationArgs: [] });
  }

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Treat any '--config-dir must exist and contain a regular sixtytwo.yaml' report (error 102) as the actionable message — that is what you will actually see.
  2. Ensure --config-dir is a directory containing a regular sixtytwo.yaml file (not a symlink-to-dir, not a file, not a missing file).
  3. File an issue / fix the dead throw at ito.js:132: either give the catch a parameter and re-throw only on genuine fs errors, or rethrow this inner error verbatim so the discriminating message surfaces.

Example fix

// before (scripts/ito.js:126-138) — inner message is masked
  try {
    const resolved = fs.realpathSync.native(configDirectory);
    if (!fs.statSync(resolved).isDirectory()
        || !fs.statSync(path.join(resolved, 'sixtytwo.yaml')).isFile()) {
      throw new Error('invalid qualification configuration');
    }
  } catch {
    throw new Error('--config-dir must exist and contain a regular sixtytwo.yaml ...');
  }
// after — only re-wrap genuine fs errors, let the validation message through
  let resolved;
  try {
    resolved = fs.realpathSync.native(configDirectory);
  } catch {
    throw new Error('--config-dir must exist and contain a regular sixtytwo.yaml ...');
  }
  if (!fs.statSync(resolved).isDirectory()
      || !fs.statSync(path.join(resolved, 'sixtytwo.yaml')).isFile()) {
    throw new Error('invalid qualification configuration');
  }
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require('fs');
const path = require('path');
function isQualificationConfigValid(configDirectory) {
  let resolved;
  try { resolved = fs.realpathSync.native(configDirectory); }
  catch { return false; }
  try {
    return fs.statSync(resolved).isDirectory()
      && fs.statSync(path.join(resolved, 'sixtytwo.yaml')).isFile();
  } catch { return false; }
}

Try / catch

// Distinguish the three failure modes the source conflates:
try {
  validateNodeQualificationArgs(args, env);
} catch (err) {
  if (err.message.startsWith('--config-dir must exist')) {
    // could be: missing dir, missing file, wrong type, or perms — re-check to disambiguate
    const dirOk = fs.existsSync(configDir) && fs.statSync(configDir).isDirectory();
    const yamlOk = dirOk && fs.statSync(path.join(configDir, 'sixtytwo.yaml')).isFile();
    log.error('config-dir invalid', { dirOk, yamlOk, configDir });
  }
  throw err;
}

Prevention

When it happens

Trigger: The code path requires --config-dir to resolve (realpath succeeds), then either `fs.statSync(resolved).isDirectory()` is false (config-dir is a file/symlink-to-file/device) OR `fs.statSync(path.join(resolved, 'sixtytwo.yaml')).isFile()` is false (missing file, or sixtytwo.yaml is a directory/symlink). When triggered, the catch at ito.js:134 swallows this error and throws '--config-dir must exist and contain a regular sixtytwo.yaml before any process is started.'

Common situations: Operator points --config-dir at a regular file rather than a directory; or sixtytwo.yaml exists but is a directory (e.g. created via `mkdir sixtytwo.yaml`). In both cases the user sees error 102's message, not this one. Anyone reading the source will see this string but it never surfaces.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/2040e1cf5c61285a. Report an issue: GitHub.