{"record":{"id":"932b13eb99c97870","repo":"transloadit/uppy","slug":"signrequest-must-be-a-function-932b13","errorCode":null,"errorMessage":"signRequest must be a function","messagePattern":"signRequest must be a function","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"critical","filePath":"packages/@uppy/aws-s3/src/s3-client/S3mini.ts","lineNumber":65,"sourceCode":"  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))\n\n      this.getCredentials = getCredentials\n      this.signRequest = this._createCredentialBasedSigner()\n    } else {\n      throw new TypeError(\n        'Either signRequest or getCredentials must be provided',","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/aws-s3/src/s3-client/S3mini.ts#L47-L83","documentation":"S3mini validates that signRequest, when provided, is a function. Passing anything else (a string, object, or the result of calling the function instead of the function itself) throws this TypeError before any request is made.","triggerScenarios":"new S3mini({ signRequest: '/api/s3/sign' }) (passing a URL string instead of a function), or signRequest: await getSigner() where the promise already resolved to a non-function, or signRequest: mySigner() invoking instead of referencing the callback.","commonSituations":"Confusing the presign endpoint URL with the callback; passing an object like {url: ...} from a config file; accidentally invoking the function during wiring; JSON configs that can't hold functions.","solutions":["Pass an async function receiving ({method, key, uploadId, partNumber}) and returning {url}","If you meant client-side signing, pass endpoint plus getCredentials instead of a URL string","Double-check you're passing the function reference, not its return value"],"exampleFix":"// before\nnew S3mini({ signRequest: '/api/s3/sign' }) // throws\n\n// after\nnew S3mini({\n  signRequest: async (req) =>\n    (await fetch('/api/s3/sign', { method: 'POST', body: JSON.stringify(req) })).json(),\n})","handlingStrategy":"type-guard","validationCode":"if ('signRequest' in cfg && typeof cfg.signRequest !== 'function') throw new TypeError('signRequest must be a function')","typeGuard":"const isSignRequestFn = (f: unknown): f is IT.SignRequestFn => typeof f === 'function'","tryCatchPattern":null,"preventionTips":["Pass the function reference, never its result or a URL string","Use TypeScript's S3Config type to catch this at compile time","Unit-test the config builder before constructing the client"],"tags":["aws-s3","configuration","type-validation","signing"],"backgroundTag":"invalid-constructor-arguments","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}