windmill-labs/windmill · error · Error
--upload '${spec}' must be <script>[:<param>]=<file-or-s3-ur
Error message
--upload '${spec}' must be <script>[:<param>]=<file-or-s3-uri> What it means
Syntax validation in parseUploadBinding: the --upload spec doesn't match <script>[:<param>]=<file-or-s3-uri>. The parser splits on the first '=' and expects a non-empty script token on the left and a source on the right; the throw fires when either side is missing — e.g. no '=' at all, empty script name, or empty source. The input at fault is the --upload string as typed.
Source
Thrown at cli/src/commands/pipeline/pipelineUpload.ts:21
// `data_upload` / `webhook` entry point so it (and its downstream) runs in the
// cascade instead of being skipped for want of input;
// `--arg <script>:<param>=<value>` passes a plain (non-S3Object) run arg.
import { basename } from "node:path";
export type UploadBinding = { scriptTok: string; param?: string; source: string };
/**
* Parse a `--upload` spec: `<script>[:<param>]=<file-or-s3-uri>`.
* Split on the FIRST `=` so an `s3://…` source (whose `:` sits to the right of
* it) stays unambiguous; an optional `:<param>` on the left names the target
* S3Object argument when the script declares more than one.
*/
export function parseUploadBinding(spec: string): UploadBinding {
const eq = spec.indexOf("=");
const left = eq < 0 ? "" : spec.slice(0, eq).trim();
const source = eq < 0 ? "" : spec.slice(eq + 1).trim();
if (!left || !source) {
throw new Error(`--upload '${spec}' must be <script>[:<param>]=<file-or-s3-uri>`);
}
const colon = left.indexOf(":");
if (colon < 0) return { scriptTok: left, source };
const scriptTok = left.slice(0, colon).trim();
const param = left.slice(colon + 1).trim();
if (!scriptTok || !param) {
throw new Error(`--upload '${spec}' must be <script>[:<param>]=<file-or-s3-uri>`);
}
return { scriptTok, param, source };
}
export type ArgBinding = { scriptTok: string; param: string; value: unknown };
/**
* Parse an `--arg` spec: `<script>:<param>=<value>`. Split on the FIRST `=`
* (values may contain `=`); the value is JSON when it parses as JSON, else the
* raw string — so `stats:limit=10` is a number and
* `daily_report:partition=2026-07-02` a string. `:<param>` is required: unlikeView on GitHub (pinned to e474e8803c)
Solutions
- Use the documented shape: --upload myscript=./data.csv or --upload myscript:input_file=s3://bucket/key
- Check for shell-quoting issues that stripped the '=' or the value
- Ensure neither side of the first '=' is empty
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at cli/src/commands/pipeline/pipelineUpload.ts:21 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/2ec04820789aa857.
Report an issue: GitHub.