transloadit/uppy · critical · TypeError

getCredentials must be a function

Error message

getCredentials must be a function

What it means

When the getCredentials strategy is used, S3mini validates that getCredentials — if provided — is a function returning {credentials: {accessKeyId, secretAccessKey, sessionToken}, region}. Passing a non-function (string, object, or invoked result) throws this TypeError immediately in the constructor.

Source

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

      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))

      this.getCredentials = getCredentials
      this.signRequest = this._createCredentialBasedSigner()
    } else {
      throw new TypeError(
        'Either signRequest or getCredentials must be provided',
      )
    }

    this.region = region
    this.requestSizeInBytes = requestSizeInBytes
  }

  /** Creates a presigner that fetches/caches credentials and generates pre-signed URLs. */
  private _createCredentialBasedSigner(): IT.SignRequestFn {
    return async (

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Pass an async function that fetches and returns {credentials, region}, e.g. hitting your backend's credential endpoint
  2. If you truly have static creds, wrap them: getCredentials: async () => ({ credentials: {...}, region })
  3. Verify the return shape includes accessKeyId/secretAccessKey (and sessionToken for temporary creds)

Example fix

// before
new S3mini({ endpoint, getCredentials: myCredsObject }) // throws

// after
new S3mini({
  endpoint,
  getCredentials: async () => (await fetch('/api/s3/credentials')).json(),
})
Defensive patterns

Strategy: type-guard

Validate before calling

if ('getCredentials' in cfg && cfg.getCredentials != null && typeof cfg.getCredentials !== 'function') throw new TypeError('getCredentials must be a function')

Type guard

const isGetCredentialsFn = (f: unknown): f is IT.GetCredentialsFn => typeof f === 'function'

Prevention

When it happens

Trigger: new S3mini({ endpoint, getCredentials: '/api/s3/credentials' }) (URL instead of function), or getCredentials: credsObject where the fetched credentials were passed directly rather than a callback that fetches them.

Common situations: Passing a static credentials object instead of a refreshable callback (breaks STS session renewal); confusing the endpoint URL with the credential-fetcher; invoking the function during wiring.

Related errors


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