{"record":{"id":"37e9d1bfcf2f55e0","repo":"RocketChat/Rocket.Chat","slug":"customoauth-failed-to-extract-username","errorCode":null,"errorMessage":"CustomOAuth: Failed to extract username","messagePattern":"CustomOAuth: Failed to extract username","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/auth-providers/custom-oauth/customOAuth.ts","lineNumber":140,"sourceCode":"\t\tthis.name = name;\n\t\tthis.options = options;\n\t\tthis.config = config;\n\n\t\tthis.addHookToProcessUser();\n\t}\n\n\tgetUsername(data: Record<string, any>) {\n\t\ttry {\n\t\t\tconst value = fromTemplate(this.usernameField, data);\n\n\t\t\tif (!value) {\n\t\t\t\tlogger.debug({ msg: 'Username field not found in data', usernameField: this.usernameField, data });\n\t\t\t\tthrow new Meteor.Error('field_not_found', `Username field \"${this.usernameField}\" not found in data`);\n\t\t\t}\n\n\t\t\treturn value as string;\n\t\t} catch (error) {\n\t\t\tthrow new Error('CustomOAuth: Failed to extract username', { cause: error });\n\t\t}\n\t}\n\n\tgetEmail(data: Record<string, any>) {\n\t\ttry {\n\t\t\tconst value = fromTemplate(this.emailField, data);\n\n\t\t\tif (!value) {\n\t\t\t\tlogger.debug({ msg: 'Email field not found in data', emailField: this.emailField, data });\n\t\t\t\tthrow new Meteor.Error('field_not_found', `Email field \"${this.emailField}\" not found in data`);\n\t\t\t}\n\t\t\treturn value as string;\n\t\t} catch (error) {\n\t\t\tthrow new Error('CustomOAuth: Failed to extract email', { cause: error });\n\t\t}\n\t}\n\n\tgetCustomName(data: Record<string, any>) {","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/auth-providers/custom-oauth/customOAuth.ts#L122-L158","documentation":"Generic wrapper thrown by getUsername's catch block around the field extraction. In almost all cases the cause is the inner Meteor.Error('field_not_found') from error 635 (template resolved to nothing), but it also wraps hard errors from fromTemplate itself, such as an invalid regex in a {{...::path}} username template. The real reason is preserved in error.cause.","triggerScenarios":"usernameField configured but missing from the provider's identity payload (cause: field_not_found with the offending template); malformed usernameField template like '{{/((/::login}}' causing fromTemplate's new RegExp to throw SyntaxError.","commonSituations":"Field mapping typo; provider schema drift; copy-pasted template syntax errors from OAuth config docs.","solutions":["Unwrap error.cause to get the precise failure (field_not_found vs template syntax error)","Fix or clear the usernameField mapping based on the provider's actual /me response","Validate the template offline: unit-test fromTemplate(usernameField, sampleIdentity) before saving the config"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n\tawait oauthLogin();\n} catch (e) {\n\tconst cause = (e as Error & { cause?: unknown }).cause;\n\tif (cause instanceof Meteor.Error && cause.error === 'field_not_found') {\n\t\t// cause.reason names the missing usernameField — fix the mapping\n\t} else throw e;\n}","preventionTips":["Always unwrap .cause on CustomOAuth wrapper errors before reporting","Unit-test fromTemplate(usernameField, samplePayload) in CI for every custom OAuth app","Watch the CustomOAuth debug logs during first login after any config change"],"tags":["custom-oauth","oauth","field-mapping","error-wrapping"],"backgroundTag":"oauth-field-mapping-failed","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}