santifer/career-ops · info

⚠️ ${label}: skipping — ${reason}

Error message

⚠️  ${label}: skipping — ${reason}

What it means

warnSkip in plugins/_engine.mjs is the plugin engine's standard notice that a plugin was skipped and why. It only formats and prints the message; the actual skip decision happens at call sites (e.g. disallowed env vars detected by isReservedEnv, plugin outside the root directory per isWithinDirectory, missing config). It is informational: the plugin did not run, and the pipeline continues with the remaining plugins.

Source

Thrown at plugins/_engine.mjs:62

export const RESERVED_ENV = new Set([
  'GEMINI_API_KEY', 'GEMINI_MODEL',
  'OPENROUTER_API_KEY', 'CAREER_OPS_MODEL',
  'OPENAI_API_KEY', 'OPENAI_BASE_URL', 'OPENAI_MODEL',
  'ANTHROPIC_API_KEY',
  'CAREER_OPS_PORTALS', 'CAREER_OPS_PROFILE',
  'PATH', 'HOME', 'NODE_OPTIONS', 'LD_PRELOAD', 'NODE_EXTRA_CA_CERTS',
]);

const ID_RE = /^[a-z0-9][a-z0-9-]*$/;
const DEFAULT_HOOK_TIMEOUT_MS = 15_000;
const MAX_REDIRECTS = 5;

function isReservedEnv(name) {
  return RESERVED_ENV.has(name) || /^AWS_/.test(name);
}

function warnSkip(label, reason) {
  console.warn(`⚠️  ${label}: skipping — ${reason}`);
}

function isWithinDirectory(rootAbs, candidateAbs) {
  const rel = path.relative(rootAbs, candidateAbs);
  return rel === '' || (!rel.startsWith(`..${path.sep}`) && rel !== '..' && !path.isAbsolute(rel));
}

function nearestExistingPath(absPath) {
  let current = path.resolve(absPath);
  while (!existsSync(current)) {
    const parent = path.dirname(current);
    if (parent === current) return null;
    current = parent;
  }
  return current;
}

function isSafePluginPath(rootAbs, candidateAbs) {

View on GitHub (pinned to 1696bec4d0)

Solutions

  1. Read the <reason> part of the message — it names the exact precondition that failed (blocked env var, path outside root, missing config)
  2. If the needed value is reserved/blocked (e.g. AWS_*), provide the credential through the plugin's own dedicated variable name instead of a reserved one
  3. If the path check skipped the plugin, install/symlink-resolve the plugin inside the project root directory
  4. Export the required environment variable in the shell or CI environment and re-run the plugin engine

Example fix

// before: plugin wants blocked var
// plugins.yml:  env: [AWS_SECRET_ACCESS_KEY]  → ⚠️ myplugin: skipping — reserved env AWS_SECRET_ACCESS_KEY
// after: use a dedicated, non-reserved variable
// plugins.yml:  env: [MYPLUGIN_AWS_KEY]
export MYPLUGIN_AWS_KEY=...   # then re-run the engine
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'fs';
const RESERVED = new Set(['PATH', 'HOME', 'SHELL', 'AWS_SECRET_ACCESS_KEY']);
function pluginWillRun(name, env, pluginPath, root) {
  const badEnv = env.filter(v => RESERVED.has(v) || v.startsWith('AWS_'));
  if (badEnv.length) return `blocked env: ${badEnv.join(',')}`;
  if (!existsSync(pluginPath)) return 'plugin file missing';
  if (!path.resolve(pluginPath).startsWith(path.resolve(root))) return 'plugin outside root';
  return null;
}

Try / catch

const results = await engine.runPlugins();
for (const r of results) {
  if (r.skipped) console.warn(`${r.name} did not run: ${r.reason} — pipeline output may be incomplete`);
}

Prevention

When it happens

Trigger: Loading/running plugins when a plugin requires an environment variable that is reserved or blocked (RESERVED_ENV names or any AWS_* var, to prevent credential leakage into plugins), the plugin file resolves outside the allowed root directory (path traversal guard), or plugin-specific preconditions (missing config/credentials) fail.

Common situations: A user sets AWS_SECRET_ACCESS_KEY globally and a plugin requests it — the engine refuses and skips; a plugin is symlinked or installed outside the project root and fails the isWithinDirectory containment check; a plugin's required env var simply isn't exported in the current shell or CI job.

Related errors


AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01). Data as JSON: /api/errors/d480811f0afbc291. Report an issue: GitHub.