{"record":{"id":"2652feb3d32175bf","repo":"windmill-labs/windmill","slug":"invalid-s3-mode-argument","errorCode":null,"errorMessage":"Invalid S3 mode argument: {}","messagePattern":"Invalid S3 mode argument: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-sql/src/lib.rs","lineNumber":180,"sourceCode":"        Some(x) => x,\n        None => return Ok(None),\n    };\n    let args_str = cap\n        .get(1)\n        .map(|x| x.as_str().to_string())\n        .unwrap_or_default();\n\n    let mut prefix = None;\n    let mut storage = None;\n    let mut format = S3ModeFormat::Json;\n\n    for kv in args_str.split(' ').map(|kv| kv.trim()) {\n        if kv.is_empty() {\n            continue;\n        }\n        let mut it = kv.split('=');\n        let (Some(key), Some(value)) = (it.next(), it.next()) else {\n            return Err(anyhow!(\"Invalid S3 mode argument: {}\", kv));\n        };\n        match (key.trim(), value.trim()) {\n            (\"prefix\", _) => prefix = Some(value.to_string()),\n            (\"storage\", _) => storage = Some(value.to_string()),\n            (\"format\", \"json\") => format = S3ModeFormat::Json,\n            (\"format\", \"parquet\") => format = S3ModeFormat::Parquet,\n            (\"format\", \"csv\") => format = S3ModeFormat::Csv,\n            (\"format\", format) => return Err(anyhow!(\"Invalid S3 mode format: {}\", format)),\n            (_, _) => return Err(anyhow!(\"Invalid S3 mode argument: {}\", kv)),\n        }\n    }\n\n    Ok(Some(S3ModeArgs { prefix, storage, format }))\n}\n\npub fn parse_sql_blocks(code: &str, track_dollar_quotes: bool) -> Vec<&str> {\n    let mut blocks = vec![];\n    let mut last_idx = 0;","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-sql/src/lib.rs#L162-L198","documentation":"In S3 mode, a SQL script's return/parameter type carries inline options as a space-separated list of `key=value` pairs (e.g. `s3:// prefix=foo storage=r2 format=parquet`). `parse_s3_mode` splits that string and raises this error when any token lacks an `=` separator, i.e. it is not a valid `key=value` argument.","triggerScenarios":"Calling `parse_s3_mode` (from `do_postgresql`, `do_mysql`, `do_bigquery`, `do_mssql`, `do_snowflake`, `do_oracledb` when the s3-mode extension is present) with an s3-mode argument string containing a bare token with no `=`, such as `s3:// prefix` or `format` without a value.","commonSituations":"Hand-editing the s3 type extension and dropping the `=` or the value (`format` instead of `format=parquet`); using spaces inside a value without quoting so it splits into bare tokens; typos like `prefix:foo`; copying an s3 mode string from docs with truncated options.","solutions":["Rewrite the s3-mode options as `key=value` pairs separated by single spaces: `prefix=x storage=y format=parquet`.","Check the full message — the offending token is printed after the colon — and add the missing `=` or value.","Ensure values don't contain unescaped spaces; avoid spaces in prefixes/storage names.","Keep `format` limited to `json` or `parquet` (other keys/values have their own validation)."],"exampleFix":"// before\ns3:// prefix format\n\n// after\ns3:// prefix=my-folder format=parquet","handlingStrategy":"validation","validationCode":"// Rust: validate s3-mode options are all key=value before calling the parser\nfn valid_s3_mode_opts(opts: &str) -> bool {\n    opts.split(' ')\n        .map(str::trim)\n        .filter(|kv| !kv.is_empty())\n        .all(|kv| kv.split_once('=').map_or(false, |(k, v)| !k.is_empty() && !v.is_empty()))\n}","typeGuard":null,"tryCatchPattern":"// Rust\nmatch parse_s3_mode(args_str) {\n    Ok(mode) => mode,\n    Err(e) if e.to_string().contains(\"Invalid S3 mode argument\") => {\n        eprintln!(\"{e} — expected key=value pairs like 'prefix=x format=parquet'\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always write s3 options as `key=value` pairs separated by single spaces.","Never include bare tokens or `key:` style separators in the s3 extension string.","Avoid spaces inside values (prefix/storage names) so splitting is unambiguous.","Keep `format` restricted to `json` or `parquet`."],"tags":["sql","s3","argument-parsing","syntax"],"backgroundTag":"invalid-s3-mode-args","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}