{"record":{"id":"8ba49590c6db5e7e","repo":"transloadit/uppy","slug":"either-signrequest-or-getcredentials-must-be-provi","errorCode":null,"errorMessage":"Either signRequest or getCredentials must be provided","messagePattern":"Either signRequest or getCredentials must be provided","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"critical","filePath":"packages/@uppy/aws-s3/src/s3-client/S3mini.ts","lineNumber":59,"sourceCode":"  readonly region: string\n  readonly requestSizeInBytes: number\n\n  private readonly getCredentials?: IT.GetCredentialsFn\n  private cachedCredentials?: IT.CredentialsResponse\n  private cachedCredentialsPromise?: Promise<IT.CredentialsResponse>\n  private signRequest!: IT.SignRequestFn\n\n  constructor({\n    region = 'auto',\n    requestSizeInBytes = C.DEFAULT_REQUEST_SIZE_IN_BYTES,\n    requestAbortTimeout,\n    ...rest\n  }: IT.S3Config) {\n    super({ requestAbortTimeout })\n    if ('signRequest' in rest) {\n      const { signRequest } = rest\n      if (!signRequest) {\n        throw new TypeError(\n          'Either signRequest or getCredentials must be provided',\n        )\n      }\n\n      if (signRequest && typeof signRequest !== 'function') {\n        throw new TypeError('signRequest must be a function')\n      }\n\n      this.signRequest = signRequest\n    } else if ('getCredentials' in rest) {\n      const { getCredentials, endpoint } = rest\n      if (typeof endpoint !== 'string' || endpoint.trim().length === 0) {\n        throw new TypeError(C.ERROR_ENDPOINT_REQUIRED)\n      }\n      if (getCredentials && typeof getCredentials !== 'function') {\n        throw new TypeError('getCredentials must be a function')\n      }\n      this.endpoint = new URL(this._ensureValidUrl(endpoint))","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/aws-s3/src/s3-client/S3mini.ts#L41-L77","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Provide a real signRequest function, or switch to the getCredentials + endpoint configuration","Strip undefined keys before constructing: remove signRequest from the object when it's not available","If using getCredentials, make sure the config object doesn't also contain a signRequest: undefined key"],"exampleFix":"// before\nconst cfg = getOptions() // { signRequest: undefined }\nnew S3mini(cfg) // throws\n\n// after\nconst cfg = getOptions()\nnew S3mini(signRequest ? { signRequest } : { getCredentials, endpoint })","handlingStrategy":"validation","validationCode":"const hasSigner = typeof opts.signRequest === 'function'\nconst hasCreds = typeof opts.getCredentials === 'function'\nif (!hasSigner && !hasCreds) throw new Error('S3mini needs signRequest or getCredentials')","typeGuard":"const hasAuth = (o: Partial<IT.S3Config>): o is IT.S3Config => typeof o.signRequest === 'function' || typeof o.getCredentials === 'function'","tryCatchPattern":"try { new S3mini(cfg) } catch (e) { if (e instanceof TypeError && /signRequest or getCredentials/.test(e.message)) { /* fix config before retrying */ } }","preventionTips":["Type the config as S3Config so TS rejects bad shapes","Delete undefined auth keys before constructing","Construct S3mini only after auth options are resolved"],"tags":["aws-s3","configuration","constructor-validation","typescript"],"backgroundTag":"invalid-constructor-arguments","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}