anomalyco/sst · error · VisibleError
Copy destination path "${to}" must be relative
Error message
Copy destination path "${to}" must be relative What it means
normalizeCopyFiles() validates the `copyFiles` option of SST Functions. The destination path (`to`, defaulting to `from`) is joined into the bundle, so absolute paths make no sense and are rejected with this VisibleError.
Source
Thrown at platform/src/components/aws/function.ts:2019
maxAge: url.cors.maxAge && toSeconds(url.cors.maxAge),
};
return {
authorization,
cors,
route: normalizeRouteArgs(url.router, url.route),
};
});
}
function normalizeCopyFiles() {
return output(args.copyFiles ?? []).apply((copyFiles) =>
Promise.all(
copyFiles.map(async (entry) => {
const from = path.join($cli.paths.root, entry.from);
const to = entry.to || entry.from;
if (path.isAbsolute(to)) {
throw new VisibleError(
`Copy destination path "${to}" must be relative`,
);
}
const stats = await fs.promises.stat(from);
const isDir = stats.isDirectory();
return { from, to, isDir };
}),
),
);
}
function normalizeVpc() {
// "vpc" is undefined
if (!args.vpc) return;
// "vpc" is a Vpc componentView on GitHub (pinned to a0bd20f762)
Solutions
- Change `to` to a path relative to the bundle root, e.g. "config/config.json"
- Also make `from` (and thus the defaulted `to`) relative to the app root if it was absolute
Example fix
// before
copyFiles: [{ from: "config/app.json", to: "/etc/app/app.json" }]
// after
copyFiles: [{ from: "config/app.json", to: "config/app.json" }] Defensive patterns
Strategy: validation
Validate before calling
import path from "path";
for (const f of args.copyFiles ?? []) {
const to = f.to || f.from;
if (path.isAbsolute(to)) throw new Error(`copyFiles 'to' must be relative: ${to}`);
} Type guard
const isRelativeCopy = (f: { from: string; to?: string }) =>
!path.isAbsolute(f.to || f.from); Try / catch
try {
const fn = new sst.aws.Function("Fn", { copyFiles });
} catch (e) {
if ((e as Error).message.includes("must be relative")) {
console.error("Use bundle-relative paths for copyFiles destinations");
}
throw e;
} Prevention
- Always express copyFiles paths relative to the app root (from) and bundle (to)
- Never use path.resolve() or OS-absolute paths in copyFiles entries
When it happens
Trigger: Passing copyFiles: [{ from: "config/x.json", to: "/etc/app/config.json" }] — an absolute `to` path; `entry.to` empty and `entry.from` absolute.
Common situations: Reusing OS-absolute destination paths from Docker or server configs inside Lambda bundle copy rules; building paths with path.resolve() instead of relative strings.
Related errors
- You must provide a KMS key via `kmsKey` when configuring `cu
- Cannot set both "logging.retention" and "logging.logGroup"
- Durable functions require "logging.format" to be set to "jso
- The "vpc.subnets" property has been renamed to "vpc.privateS
- result.errors.join("\n")
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/3a3624b1f2e9853b.
Report an issue: GitHub.