{"record":{"id":"839ea1ceec74f95c","repo":"windmill-labs/windmill","slug":"upload-binds-scriptpath-param-more-than-on","errorCode":null,"errorMessage":"--upload binds ${scriptPath}:${param} more than once.","messagePattern":"--upload binds (.+?):(.+?) more than once\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/pipeline/pipeline.ts","lineNumber":504,"sourceCode":"    return schema;\n  };\n\n  const args: Record<string, any> = {};\n  for (const binding of bindings) {\n    let param = binding.param;\n    if (!param) {\n      const params = s3ObjectParams(await loadSchema());\n      if (params.length === 1) param = params[0];\n      else if (params.length === 0) {\n        throw new Error(`${scriptPath} declares no S3Object parameter to bind --upload to.`);\n      } else {\n        throw new Error(\n          `${scriptPath} has multiple S3Object parameters (${params.join(\", \")}) — pick one with --upload ${binding.scriptTok}:<param>=${binding.source}`,\n        );\n      }\n    }\n    if (param in args) {\n      throw new Error(`--upload binds ${scriptPath}:${param} more than once.`);\n    }\n    let obj: { s3: string; storage?: string };\n    if (binding.source.startsWith(\"s3://\")) {\n      // Canonical `s3://<storage>/<key>`; keeps named storage (see parseS3Uri).\n      obj = parseS3Uri(binding.source);\n    } else {\n      const buf = await readFile(binding.source);\n      // Key scoped by script + param so distinct sources sharing a basename\n      // (across scripts or params) don't clobber each other in the store.\n      const key = devUploadKey(scriptPath, param, binding.source);\n      await wmill.fileUpload({\n        workspace: workspaceId,\n        fileKey: key,\n        requestBody: new Blob([buf]) as any,\n      });\n      log.info(colors.gray(`  ↑ ${binding.source} → s3://${key}`));\n      obj = { s3: key };\n    }","sourceCodeStart":486,"sourceCodeEnd":522,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/pipeline/pipeline.ts#L486-L522","documentation":"Duplicate-binding guard in resolveUploadArgs: two or more --upload bindings target the same script and the same parameter, which would have the later upload silently clobber the earlier one. The inputs at fault are the repeated --upload <script>:<param>=… entries on the command line for one pipeline run.","triggerScenarios":"Thrown at cli/src/commands/pipeline/pipeline.ts:504 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Remove the duplicate --upload entry so each param is bound exactly once","If you meant two different params, fix the param name in one of the bindings","If you meant two files into two params, give each binding its own explicit :<param>"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}