{"record":{"id":"3a3624b1f2e9853b","repo":"anomalyco/sst","slug":"copy-destination-path-to-must-be-relative","errorCode":null,"errorMessage":"Copy destination path \"${to}\" must be relative","messagePattern":"Copy destination path \"(.+?)\" must be relative","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/function.ts","lineNumber":2019,"sourceCode":"                  maxAge: url.cors.maxAge && toSeconds(url.cors.maxAge),\n                };\n\n        return {\n          authorization,\n          cors,\n          route: normalizeRouteArgs(url.router, url.route),\n        };\n      });\n    }\n\n    function normalizeCopyFiles() {\n      return output(args.copyFiles ?? []).apply((copyFiles) =>\n        Promise.all(\n          copyFiles.map(async (entry) => {\n            const from = path.join($cli.paths.root, entry.from);\n            const to = entry.to || entry.from;\n            if (path.isAbsolute(to)) {\n              throw new VisibleError(\n                `Copy destination path \"${to}\" must be relative`,\n              );\n            }\n\n            const stats = await fs.promises.stat(from);\n            const isDir = stats.isDirectory();\n\n            return { from, to, isDir };\n          }),\n        ),\n      );\n    }\n\n    function normalizeVpc() {\n      // \"vpc\" is undefined\n      if (!args.vpc) return;\n\n      // \"vpc\" is a Vpc component","sourceCodeStart":2001,"sourceCodeEnd":2037,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/function.ts#L2001-L2037","documentation":"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.","triggerScenarios":"Passing copyFiles: [{ from: \"config/x.json\", to: \"/etc/app/config.json\" }] — an absolute `to` path; `entry.to` empty and `entry.from` absolute.","commonSituations":"Reusing OS-absolute destination paths from Docker or server configs inside Lambda bundle copy rules; building paths with path.resolve() instead of relative strings.","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"],"exampleFix":"// before\ncopyFiles: [{ from: \"config/app.json\", to: \"/etc/app/app.json\" }]\n// after\ncopyFiles: [{ from: \"config/app.json\", to: \"config/app.json\" }]","handlingStrategy":"validation","validationCode":"import path from \"path\";\nfor (const f of args.copyFiles ?? []) {\n  const to = f.to || f.from;\n  if (path.isAbsolute(to)) throw new Error(`copyFiles 'to' must be relative: ${to}`);\n}","typeGuard":"const isRelativeCopy = (f: { from: string; to?: string }) =>\n  !path.isAbsolute(f.to || f.from);","tryCatchPattern":"try {\n  const fn = new sst.aws.Function(\"Fn\", { copyFiles });\n} catch (e) {\n  if ((e as Error).message.includes(\"must be relative\")) {\n    console.error(\"Use bundle-relative paths for copyFiles destinations\");\n  }\n  throw e;\n}","preventionTips":["Always express copyFiles paths relative to the app root (from) and bundle (to)","Never use path.resolve() or OS-absolute paths in copyFiles entries"],"tags":["aws","lambda","copy-files","path-validation"],"backgroundTag":"absolute-path-not-allowed","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}