transloadit/uppy · error · TypeError
s3Endpoint must be a string
Error message
s3Endpoint must be a string
What it means
Each Companion provider class exposes an oauthProvider string identifying the grant provider (e.g. 'google', 'dropbox'). If the provider class for the requested provider has a null/empty oauthProvider, Companion cannot build the grant authorize URL and returns 400.
Source
Thrown at packages/@uppy/aws-s3/src/index.ts:191
this.#setResumableUploadsCapability(true)
this.#queue.clear()
}
// --------------------------------------------------------------------------
// S3 Client Initialization
// --------------------------------------------------------------------------
#initS3Client(): void {
if ('companionEndpoint' in this.opts) {
if (typeof this.opts.companionEndpoint !== 'string') {
throw new TypeError('companionEndpoint must be a string')
}
this.#s3Client = new S3Companion({
companionEndpoint: this.opts.companionEndpoint,
})
} else if ('getCredentials' in this.opts) {
if (typeof this.opts.s3Endpoint !== 'string') {
throw new TypeError('s3Endpoint must be a string')
}
if (typeof this.opts.getCredentials !== 'function') {
throw new TypeError('getCredentials must be a function')
}
if (this.opts.region != null && typeof this.opts.region !== 'string') {
throw new TypeError('region must be a string')
}
// Mode: Temporary credentials (client-side signing)
this.#s3Client = new S3mini({
endpoint: this.opts.s3Endpoint,
getCredentials: this.opts.getCredentials,
region: this.opts.region,
})
} else if ('signRequest' in this.opts) {
if (typeof this.opts.signRequest !== 'function') {
throw new TypeError('signRequest must be a function')
}View on GitHub (pinned to 5d4dedd02a)
Solutions
- If using a custom provider, set `static oauthProvider = 'mygrantprovider'` (matching the grant config key)
- Do not call /connect/:providerName for providers that are not OAuth-based
- Verify the provider class version matches the Companion version (API changes across upgrades)
Example fix
// before
class MyProvider extends Provider { /* missing oauthProvider */ }
// after
class MyProvider extends Provider {
static oauthProvider = 'myprovider'
// ...
} Defensive patterns
Strategy: type-guard
Type guard
class MyProvider extends Provider {
static oauthProvider = 'myprovider'
}
const hasOAuthProvider = (C: typeof Provider): C is typeof Provider & { oauthProvider: string } =>
typeof (C as any).oauthProvider === 'string' && (C as any).oauthProvider.length > 0 Prevention
- Unit-test custom provider classes for required statics (id, oauthProvider)
- Only route OAuth-based providers through /connect
- Pin Companion versions and read migration notes for provider API changes
When it happens
Trigger: Using a custom provider class that forgets to set the oauthProvider static property; or a provider whose grant config does not map to an OAuth provider (some providers like local-disk or transloadit-style integrations do not use OAuth and should not go through /connect).
Common situations: Writing a custom provider and missing the static oauthProvider field; attempting to 'connect' to a non-OAuth provider via the OAuth connect endpoint.
Related errors
- Missing S3 object key for aborting upload
- Missing S3 object key for resuming upload
- Missing S3 object key for uploading part
- companionEndpoint must be a string
- Missing S3 object key for completing multipart upload
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/e9ed0b3905be1144.
Report an issue: GitHub.