transloadit/uppy · critical · TypeError
[s3mini] endpoint must be a valid URL. Expected format: http
Error message
[s3mini] endpoint must be a valid URL. Expected format: https://<host>[:port][/base-path] But provided: "${raw}" What it means
s3mini validates the endpoint URL before use and throws a TypeError if it cannot be parsed into the expected `https://<host>[:port][/base-path]` form. This guard runs in the constructor so an malformed URL fails immediately rather than producing broken signatures or cryptic XHR failures later. The offending raw value is included in the message.
Source
Thrown at packages/@uppy/aws-s3/src/s3-client/S3mini.ts:150
return this.cachedCredentialsPromise
}
private _ensureValidUrl(raw: string): string {
const candidate = /^(https?:)?\/\//i.test(raw) ? raw : `https://${raw}`
try {
new URL(candidate)
// Find the last non-slash character
let endIndex = candidate.length
while (endIndex > 0 && candidate[endIndex - 1] === '/') {
endIndex--
}
return endIndex === candidate.length
? candidate
: candidate.substring(0, endIndex)
} catch {
const msg = `${C.ERROR_ENDPOINT_FORMAT} But provided: "${raw}"`
throw new TypeError(msg)
}
}
private _checkKey(key: string): void {
if (typeof key !== 'string' || key.trim().length === 0) {
throw new TypeError(C.ERROR_KEY_REQUIRED)
}
}
private _validateUploadPartParams(
key: string,
uploadId: string,
partNumber: number,
): void {
this._checkKey(key)
if (typeof uploadId !== 'string' || uploadId.trim().length === 0) {
throw new TypeError(C.ERROR_UPLOAD_ID_REQUIRED)
}View on GitHub (pinned to 5d4dedd02a)
Solutions
- Fix the endpoint to include protocol and host: `https://s3.us-east-1.amazonaws.com` or `http://localhost:9000` for local MinIO.
- If it comes from config/env, trim and validate it at startup before constructing S3mini.
- Verify no stray characters, quotes, or newlines in the value (log `JSON.stringify(endpoint)` to see hidden whitespace).
- For local development remember http vs https matters; use `http://` only for localhost.
Example fix
// before
const s3 = new S3mini({ endpoint: process.env.S3_ENDPOINT }) // "s3.example.com"
// after
const s3 = new S3mini({ endpoint: 'https://s3.example.com' }) Defensive patterns
Strategy: validation
Validate before calling
function parseEndpoint(raw: string | undefined): URL {
const trimmed = (raw ?? '').trim()
if (!/^https?:\/\//.test(trimmed)) throw new Error(`Bad S3 endpoint: ${raw}`)
return new URL(trimmed)
}
const s3 = new S3mini({ endpoint: parseEndpoint(process.env.S3_ENDPOINT).toString(), ... }) Type guard
const isValidEndpoint = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0 && /^https?:\/\/[^\s]+$/.test(v.trim())
Prevention
- Normalize/trim endpoints from env vars and config files before use.
- Fail fast on config parse errors at startup with a descriptive message including the raw value.
When it happens
Trigger: Passing an endpoint without a scheme (`s3.example.com`), with a typo (`htp://...`), with whitespace, or a non-string (e.g. an object from env parsing). Any endpoint value that throws inside the URL-normalization logic lands in the catch and rethrows this TypeError.
Common situations: Reading the endpoint from an environment variable that is unset/malformed; copying a MinIO/Cloudflare R2/Backblaze B2 endpoint and dropping the `https://` prefix; trailing spaces from config files or YAML multiline strings; API gateway URLs with unusual characters.
Related errors
- Endpoint is required for credential-based signing
- Either signRequest or getCredentials must be provided
- signRequest must be a function
- [s3mini] endpoint must be a non-empty string
- getCredentials must be a function
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/fff3440100a5ff17.
Report an issue: GitHub.