affaan-m/ECC · error
must be a non-empty string when provided
Error message
${key} must be a non-empty string when provided What it means
readOptionalStringOption validates optional string options (e.g. projectRoot, homeDir). If the option is provided it must be a non-empty, non-whitespace string; otherwise this error is thrown. Passing null/undefined/'' is fine (treated as absent).
Solutions
- Ensure the option value is a non-empty trimmed string before calling, e.g. `String(rawPath ?? '').trim() || undefined`
- Fix the source of the value (CLI arg, env var) so it is a string
- Coerce numbers to strings explicitly if a path was parsed as a number
Example fix
// before
loadInstallManifests({ projectRoot: process.cwd().length });
// after
const root = String(process.cwd());
if (root.trim()) loadInstallManifests({ projectRoot: root }); Defensive patterns
Strategy: validation
Validate before calling
function assertOptionalString(v) { return v == null || v === '' ? null : (typeof v === 'string' && v.trim() ? v : (() => { throw new Error('option must be a non-empty string'); })()); } Type guard
const isNonEmptyString = (v) => typeof v === 'string' && v.trim().length > 0;
Try / catch
try { loadInstallManifests({ projectRoot }); } catch (e) { if (e.message.includes('must be a non-empty string')) { console.error('Fix the option value type:', e.message); } else throw e; } Prevention
- Trim and type-check path options sourced from CLI/env
- Coerce numeric or object values to strings explicitly
- Pass undefined (not whitespace) for absent options
When it happens
Trigger: Passing options like `{ projectRoot: 123 }`, `{ homeDir: ' ' }`, or an object/array instead of a string to manifest-loading APIs.
Common situations: Variables that are undefined-or-number from CLI parsing; env vars read as numbers; whitespace-only values from untrimmed input; accidental object passed where a path string is expected.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- input_artifacts must be a list of local paths
- -32602
- a claim token is required
- a confirmed nonempty coordinate is required
- a generated candidate cannot claim original-source identity
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/a854103f1d64822f.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install-manifests.js:240
description: `Install only the ${skillId} skill directory.`,
modules: [moduleId],
synthetic: true,
});
componentIds.add(componentId);
}
}
function readOptionalStringOption(options, key) {
if (
!Object.prototype.hasOwnProperty.call(options, key)
|| options[key] === null
|| options[key] === undefined
) {
return null;
}
if (typeof options[key] !== 'string' || options[key].trim() === '') {
throw new Error(`${key} must be a non-empty string when provided`);
}
return options[key];
}
function readModuleTargetsOrThrow(module) {
const moduleId = module && module.id ? module.id : '<unknown>';
const targets = module && module.targets;
if (!Array.isArray(targets)) {
throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);
}
const normalizedTargets = targets.map(target => (
typeof target === 'string' ? target.trim() : ''
));
if (normalizedTargets.some(target => target.length === 0)) {View on GitHub (pinned to 8321021c54)