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
- Read the <reason> part of the message — it names the exact precondition that failed (blocked env var, path outside root, missing config)
- 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
- If the path check skipped the plugin, install/symlink-resolve the plugin inside the project root directory
- 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
- Never request reserved or AWS_* env vars in plugin manifests; use plugin-specific variable names
- Keep plugins installed inside the project root so the containment check passes
- Export all required plugin env vars in the shell/CI before running the engine
- Parse the ⚠️ skip lines in logs and alert when an expected plugin was skipped
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
- plugin egress must use HTTPS: ${u.href}
- plugin egress to "${u.hostname}" is not in allowedHosts [${[
- refusing to hash symlink: ${childRel}
- refusing to archive restricted destination: ${preGuard.reaso
- refusing to archive restricted destination after redirect: $
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/d480811f0afbc291.
Report an issue: GitHub.