transloadit/uppy · critical · TypeError

Either signRequest or getCredentials must be provided

Error message

Either signRequest or getCredentials must be provided

What it means

S3mini's constructor requires exactly one of two auth strategies: a signRequest callback (server-side/external presigning) or getCredentials (client-side SigV4 signing). Passing signRequest: undefined/null triggers this TypeError because the key is present in the config object but falsy, which is treated as missing credentials entirely.

Source

Thrown at packages/@uppy/aws-s3/src/s3-client/S3mini.ts:59

  readonly region: string
  readonly requestSizeInBytes: number

  private readonly getCredentials?: IT.GetCredentialsFn
  private cachedCredentials?: IT.CredentialsResponse
  private cachedCredentialsPromise?: Promise<IT.CredentialsResponse>
  private signRequest!: IT.SignRequestFn

  constructor({
    region = 'auto',
    requestSizeInBytes = C.DEFAULT_REQUEST_SIZE_IN_BYTES,
    requestAbortTimeout,
    ...rest
  }: IT.S3Config) {
    super({ requestAbortTimeout })
    if ('signRequest' in rest) {
      const { signRequest } = rest
      if (!signRequest) {
        throw new TypeError(
          'Either signRequest or getCredentials must be provided',
        )
      }

      if (signRequest && typeof signRequest !== 'function') {
        throw new TypeError('signRequest must be a function')
      }

      this.signRequest = signRequest
    } else if ('getCredentials' in rest) {
      const { getCredentials, endpoint } = rest
      if (typeof endpoint !== 'string' || endpoint.trim().length === 0) {
        throw new TypeError(C.ERROR_ENDPOINT_REQUIRED)
      }
      if (getCredentials && typeof getCredentials !== 'function') {
        throw new TypeError('getCredentials must be a function')
      }
      this.endpoint = new URL(this._ensureValidUrl(endpoint))

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Provide a real signRequest function, or switch to the getCredentials + endpoint configuration
  2. Strip undefined keys before constructing: remove signRequest from the object when it's not available
  3. If using getCredentials, make sure the config object doesn't also contain a signRequest: undefined key

Example fix

// before
const cfg = getOptions() // { signRequest: undefined }
new S3mini(cfg) // throws

// after
const cfg = getOptions()
new S3mini(signRequest ? { signRequest } : { getCredentials, endpoint })
Defensive patterns

Strategy: validation

Validate before calling

const hasSigner = typeof opts.signRequest === 'function'
const hasCreds = typeof opts.getCredentials === 'function'
if (!hasSigner && !hasCreds) throw new Error('S3mini needs signRequest or getCredentials')

Type guard

const hasAuth = (o: Partial<IT.S3Config>): o is IT.S3Config => typeof o.signRequest === 'function' || typeof o.getCredentials === 'function'

Try / catch

try { new S3mini(cfg) } catch (e) { if (e instanceof TypeError && /signRequest or getCredentials/.test(e.message)) { /* fix config before retrying */ } }

Prevention

When it happens

Trigger: Constructing new S3mini({ signRequest: undefined }) or building the config dynamically so the signRequest property exists but is undefined (e.g. spread from an options object where the field was never set).

Common situations: Conditional wiring like new S3mini({...(useSigner ? {signRequest} : {})}) that still includes the key with an undefined value; reading signRequest from env/config that is missing at runtime; refactoring where the callback was renamed.

Related errors


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/8ba49590c6db5e7e. Report an issue: GitHub.