windmill-labs/windmill · error · Error
Invalid s3 object ${JSON.stringify(s3Object)}: expected an s
Error message
Invalid s3 object ${JSON.stringify(s3Object)}: expected an s3://<storage>/<key> URI (e.g. "s3:///${s3Object}" for key "${s3Object}" in the default storage) or { s3: <key> } What it means
parseS3Object normalizes an S3 object reference in typescript-client/s3Objects.ts:62, accepting either an s3://<storage>/<key> URI (s3:///<key> for default storage) or an object like { s3: <key> }. It throws this error when the input is neither a valid URI nor an object with an s3 key, e.g. a bare path or a malformed string.
Source
Thrown at typescript-client/s3Types.ts:62
/**
* Parse an S3 object from URI string or record format
* @param s3Object - S3 object as URI string (`s3://storage/key`, `s3:///key`
* for the default storage) or record. Any other string throws rather than
* falling back to an auto-generated key: an auto key is requested by
* omitting the object, and a fallback would silently misplace the upload
* on any typo.
* @returns S3 object record with storage and s3 key
*/
export function parseS3Object(s3Object: S3Object): S3ObjectRecord {
if (typeof s3Object === "object") return s3Object;
const match = s3Object.match(/^s3:\/\/([^/]*)\/(.+)$/);
if (match) return { storage: match[1] || undefined, s3: match[2] };
if (s3Object.startsWith("s3://")) {
throw new Error(
`Invalid s3 object URI ${JSON.stringify(s3Object)}: expected s3://<storage>/<key> with a non-empty key (s3:///<key> for the default storage)`
);
}
throw new Error(
`Invalid s3 object ${JSON.stringify(s3Object)}: expected an s3://<storage>/<key> URI (e.g. "s3:///${s3Object}" for key "${s3Object}" in the default storage) or { s3: <key> }`
);
}
View on GitHub (pinned to e474e8803c)
Solutions
- Wrap a bare key into the default-storage URI: `s3:///${key}`
- Pass an object form instead: `{ s3: key }` with optional `storage`
- Check the string starts with `s3://` and has a non-empty key after `<storage>/` before calling
- Trim the input; ensure it is a string, not undefined/null
Example fix
// before getPresignedS3PublicUrls(['reports/q3.json']) // after getPresignedS3PublicUrls(['s3:///reports/q3.json'])
Defensive patterns
Strategy: validation
Validate before calling
function isValidS3Object(o) {
if (typeof o === 'string') return o.startsWith('s3://') && /^s3:\/\/([^/]*\/)?.+/.test(o);
return o != null && typeof o === 'object' && typeof o.s3 === 'string' && o.s3.length > 0;
} Type guard
function isS3ObjectInput(v: unknown): v is { s3: string; storage?: string } {
return typeof v === 'object' && v !== null && 's3' in v && typeof (v as any).s3 === 'string';
} Try / catch
try {
const obj = parseS3Object(input);
} catch (e) {
console.error('Bad S3 reference, expected s3://<storage>/<key> or { s3: key }:', input, e);
throw new Error(`Invalid S3 reference: ${input}`);
} Prevention
- Always build URIs with the s3:// prefix, using s3:///<key> for default storage
- Prefer the object form { s3: key } to avoid string-format mistakes
- Validate inputs at boundaries (CLI args, config files) before calling the client
- Trim whitespace from keys read from env/config
When it happens
Trigger: Calling parseS3Object (directly or via s3Obj or getPresignedS3PublicUrls) with a value that is not an object containing an `s3` field and not a string starting with `s3://` — e.g. passing `"myfile.json"` or `"s3:"` instead of `"s3:///myfile.json"` or `{ s3: "myfile.json" }`.
Common situations: Passing a bare S3 key where a URI is expected; building the URI by string concat and dropping the `s3://` prefix; reading a path from config/CLI args that was never normalized; extra whitespace or a storage prefix typo like `s3:/storage/key`.
Related errors
- deleteS3File: s3 key is required
- Invalid s3 object URI ${JSON.stringify(s3Object)}: expected
- Invalid s3 object URI {s3_object!r}: expected s3://<storage>
- Invalid s3 object {s3_object!r}: expected an s3://<storage>/
- Invalid S3 mode format: {}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/98f75468392942ef.
Report an issue: GitHub.