mastra-ai/mastra · error · Error
Experiment worker artifacts cannot contain absolute symlinks
Error message
Experiment worker artifacts cannot contain absolute symlinks: ${artifactPath} What it means
When digesting the built artifact to write the experiment worker manifest, any symbolic link whose target is an absolute path is rejected. Absolute symlinks would break portability (they point outside the artifact and depend on the build machine's layout) and can be a security risk when artifacts are unpacked elsewhere. The build fails fast with the offending artifact-relative path.
Source
Thrown at packages/cli/src/commands/experiment/ExperimentBundler.ts:272
for (const name of entries.sort((left, right) => (left < right ? -1 : left > right ? 1 : 0))) {
const fullPath = join(directory, name);
const artifactPath = relative(root, fullPath).replaceAll('\\', '/');
if (artifactPath === 'experiment-worker-manifest.json' || artifactPath === 'node_modules') continue;
const stats = await lstat(fullPath);
if (stats.isDirectory()) {
await visit(fullPath);
} else if (stats.isFile()) {
files.push({
path: artifactPath,
sha256: createHash('sha256')
.update(await readFile(fullPath))
.digest('hex'),
});
} else if (stats.isSymbolicLink()) {
const target = await readlink(fullPath);
if (isAbsolute(target)) {
throw new Error(`Experiment worker artifacts cannot contain absolute symlinks: ${artifactPath}`);
}
const resolvedTarget = resolve(dirname(fullPath), target);
const artifactTarget = relative(root, resolvedTarget);
if (artifactTarget === '..' || artifactTarget.startsWith(`..${sep}`) || isAbsolute(artifactTarget)) {
throw new Error(`Experiment worker artifacts cannot contain escaping symlinks: ${artifactPath}`);
}
files.push({
path: artifactPath,
type: 'symlink',
target,
sha256: createHash('sha256').update(target).digest('hex'),
});
} else {
throw new Error(`Unsupported artifact file type: ${artifactPath}`);
}
}
};
await visit(root);View on GitHub (pinned to 75dd419e61)
Solutions
- Find the file listed in the message and remove or recreate the symlink as a relative symlink.
- Replace absolute symlinks with real file copies in your source/package before building.
- Check node_modules dependencies for postinstall scripts that create absolute links and pin/vendor a fixed version.
- Rebuild into a clean output directory to rule out stale links from a previous build.
Example fix
// before ln -s /home/me/project/vendor/lib ./lib // after ln -s ../vendor/lib ./lib # relative target, stays inside the artifact
Defensive patterns
Strategy: validation
Validate before calling
import { lstat, readlink, readdir } from 'node:fs/promises';
import { isAbsolute, join } from 'node:path';
async function assertNoAbsoluteSymlinks(dir: string) {
for (const e of await readdir(dir, { withFileTypes: true })) {
const p = join(dir, e.name);
if (e.isDirectory()) await assertNoAbsoluteSymlinks(p);
else if (e.isSymbolicLink() && isAbsolute(await readlink(p))) throw new Error(`absolute symlink: ${p}`);
}
} Type guard
null
Try / catch
try {
await buildExperimentWorker({ outputDir });
} catch (e) {
if (String(e?.message).includes('absolute symlinks')) {
console.error('Replace the listed symlink with a relative link or a real copy');
} else throw e;
} Prevention
- Use relative symlinks everywhere in project source and dependencies
- Avoid postinstall scripts that create absolute links
- Vendor dependencies that insist on absolute symlinks
- Build from a clean output directory to drop stale links
When it happens
Trigger: collectFileDigests encounters a symlink inside the bundler output directory whose readlink() target begins with '/', e.g. a dependency or postinstall script that created an absolute symlink into node_modules or a system path.
Common situations: A package's postinstall creating absolute symlinks; pnpm/npm linking global binaries into the output; copying files with `cp -s /abs/path` into src so the absolute link ends up in the bundle; OS/package-manager-generated links in the output directory.
Related errors
- Experiment worker artifacts cannot contain escaping symlinks
- FAIL_BUILD_SCRIPT
- FAIL_BUILD_COMMAND
- mastra-wrapper plugin did not return code, there is likely a
- Failed to copy studio assets from "${studioSource}" to "${st
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b83b7cedf2d01f50.
Report an issue: GitHub.