JuliusBrussee/caveman · error
invalid scoped package
Error message
invalid scoped package
What it means
barePackageName() parses a bare import specifier and throws "invalid scoped package" when a specifier starting with "@" does not have a scope and name — i.e. "@" alone, "@scope", or "@scope/". The parser needs a well-formed @scope/name prefix to find the package's package.json; a malformed scoped specifier cannot be resolved.
Source
Thrown at packages/agent/src/source-graph.ts:211
async function collectPackageFiles(directory: string, files: Set<string>): Promise<void> {
const entries = await opendir(directory);
for await (const entry of entries) {
if (entry.name === "node_modules" || entry.name === ".git") continue;
const path = resolve(directory, entry.name);
if (entry.isDirectory()) {
await collectPackageFiles(path, files);
} else if (entry.isFile()) {
files.add(path);
} else if (entry.isSymbolicLink()) {
throw new Error(`caveman build: package artifact symlink is not lockable: ${JSON.stringify(path)}`);
}
}
}
function barePackageName(specifier: string): string {
const parts = specifier.split("/");
if (specifier.startsWith("@")) {
if (parts.length < 2 || parts[1] === "") throw new Error("invalid scoped package");
return `${parts[0]}/${parts[1]}`;
}
if (parts[0] === "") throw new Error("invalid package");
return parts[0]!;
}
function resolvePackageExport(exportsValue: unknown, subpath: string): string | undefined {
if (typeof exportsValue === "string" || Array.isArray(exportsValue)) {
return subpath === "." ? resolveConditionalExport(exportsValue) : undefined;
}
if (!isRecord(exportsValue)) return undefined;
const keys = Object.keys(exportsValue);
if (!keys.some((key) => key.startsWith("."))) {
return subpath === "." ? resolveConditionalExport(exportsValue) : undefined;
}
if (Object.hasOwn(exportsValue, subpath)) {
return resolveConditionalExport(exportsValue[subpath]);
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Fix the specifier to a complete form: "@scope/name" or "@scope/name/subpath".
- If the specifier is computed at build time, validate it before emitting the import.
- Search the codebase for the malformed literal from the error message.
Example fix
// before import x from "@myorg/"; // after import x from "@myorg/pkg";
Defensive patterns
Strategy: type-guard
Validate before calling
const SCOPED = /^@[^/\s]+\/.+$/;
function isWellFormedBareSpecifier(spec: string): boolean {
if (spec.startsWith("@")) return SCOPED.test(spec) && !spec.endsWith("/");
return /^[^/]/.test(spec);
} Type guard
function isScopedPackageName(spec: string): boolean {
const parts = spec.split("/");
return spec.startsWith("@") && parts.length >= 2 && parts[1] !== "";
} Prevention
- Validate template-built import strings before emitting them.
- Search for malformed scoped literals like "@scope/" after refactors.
- Write specifiers as full literals ("@scope/pkg/sub") whenever possible.
When it happens
Trigger: A source file contains an import like import "@scope/" or a string built from a template that collapses to just "@scope" or "@".
Common situations: Template-built import strings with an empty submodule segment; typos like "@scope//sub"; refactors that split a specifier incorrectly.
Related errors
- caveman build: requiredFixturePassRate must be in (0,1]
- caveman build: qualityRetention must be in (0,1]
- cave_privacy_conformance_failed
- cave_live_eval_sandbox_profile_missing
- invalid package
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/d74bc9eb130067d7.
Report an issue: GitHub.