windmill-labs/windmill · error · Error
${scriptPath} has multiple S3Object parameters (${params.joi
Error message
${scriptPath} has multiple S3Object parameters (${params.join(", ")}) — pick one with --upload ${binding.scriptTok}:<param>=${binding.source} What it means
Disambiguation error while resolving a --upload binding in the pipeline run command: the target script's schema has more than one S3Object-typed parameter, no explicit param name was given in the binding, and the CLI refuses to guess which one receives the uploaded file. The message lists the candidate parameter names and shows the exact syntax to disambiguate. The inputs at fault are the --upload spec (missing :<param>) and the script's schema declaring multiple S3Object params.
Source
Thrown at cli/src/commands/pipeline/pipeline.ts:498
throw new Error(`No local file for ${scriptPath} to infer its S3Object parameter.`);
}
schema = (await inferSchema(ls.language as any, ls.content, {}, scriptPath)).schema;
} else {
schema = (await wmill.getScriptByPath({ workspace: workspaceId, path: scriptPath })).schema;
}
return schema;
};
const args: Record<string, any> = {};
for (const binding of bindings) {
let param = binding.param;
if (!param) {
const params = s3ObjectParams(await loadSchema());
if (params.length === 1) param = params[0];
else if (params.length === 0) {
throw new Error(`${scriptPath} declares no S3Object parameter to bind --upload to.`);
} else {
throw new Error(
`${scriptPath} has multiple S3Object parameters (${params.join(", ")}) — pick one with --upload ${binding.scriptTok}:<param>=${binding.source}`,
);
}
}
if (param in args) {
throw new Error(`--upload binds ${scriptPath}:${param} more than once.`);
}
let obj: { s3: string; storage?: string };
if (binding.source.startsWith("s3://")) {
// Canonical `s3://<storage>/<key>`; keeps named storage (see parseS3Uri).
obj = parseS3Uri(binding.source);
} else {
const buf = await readFile(binding.source);
// Key scoped by script + param so distinct sources sharing a basename
// (across scripts or params) don't clobber each other in the store.
const key = devUploadKey(scriptPath, param, binding.source);
await wmill.fileUpload({
workspace: workspaceId,View on GitHub (pinned to e474e8803c)
Solutions
- Re-run with the param named explicitly: --upload <script>:<param>=<file-or-s3-uri> using one of the listed candidates
- If only one param should be S3Object, change the script's schema so the other parameter is a plain string/type
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at cli/src/commands/pipeline/pipeline.ts:498 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/f230c5c23b6b5518.
Report an issue: GitHub.