transloadit/uppy · error · TypeError
signRequest must be a function
Error message
signRequest must be a function
What it means
The get controller requires an initialized provider instance on req.companion (set by middleware once the user is authenticated). If provider is falsy the request cannot proceed and 400 is returned before attempting size/stream operations.
Source
Thrown at packages/@uppy/aws-s3/src/index.ts:208
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')
}
// Mode: Custom signing function
this.#s3Client = new S3mini({
signRequest: this.opts.signRequest,
})
} else {
throw new TypeError(
'One of options `companionEndpoint`, `signRequest`, or `getCredentials` is required',
)
}
}
// --------------------------------------------------------------------------
// Upload Entry Point
// --------------------------------------------------------------------------
#upload = async (fileIDs: string[]): Promise<void> => {
if (fileIDs.length === 0) returnView on GitHub (pinned to 5d4dedd02a)
Solutions
- Verify the provider is in companionOptions.providers with valid key/secret
- Ensure the client sends a valid, unexpired token for the provider session
- Align provider names (case-sensitive) between Uppy's frontend options and Companion
- Check middleware logs to see why the provider instance was not created
Example fix
// before
companion({ providers: ['drive'] }) // client requests box
// after
companion({ providers: ['drive', 'box'], providerOptions: { box: { key: '...', secret: '...' } } }) Defensive patterns
Strategy: validation
Validate before calling
if (!enabledProviders.includes(providerName)) {
throw new Error(`provider ${providerName} not available`)
} Type guard
const isProviderAvailable = (p: string): boolean => enabledProviders.includes(p) && Boolean(providerOptions[p]?.key)
Try / catch
try {
await providerClient.get(file)
} catch (e) {
if (e.status === 400) return reAuthenticate() // session/provider missing
throw e
} Prevention
- Check token expiry before provider calls and re-auth proactively
- Mirror provider config between client and server
- Handle 400 from provider endpoints as a signal to re-run the OAuth flow
When it happens
Trigger: Requesting /get for a provider that is not enabled/configured on this Companion, or hitting the endpoint without a valid provider session so the middleware never attached the provider instance.
Common situations: Frontend configured with a provider the backend does not have key/secret for; expired/invalid uppyAuthToken so provider instantiation was skipped; mismatched provider names between frontend and Companion config.
Related errors
- region must be a string
- One of options `companionEndpoint`, `signRequest`, or `getCr
- Missing S3 object key for aborting upload
- Missing S3 object key for resuming upload
- Missing S3 object key for uploading part
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/e220f8a341ea19fb.
Report an issue: GitHub.