{"record":{"id":"599130d42d8c9a45","repo":"RocketChat/Rocket.Chat","slug":"customoauth-failed-to-extract-custom-name-599130","errorCode":null,"errorMessage":"CustomOAuth: Failed to extract custom name","messagePattern":"CustomOAuth: Failed to extract custom name","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/auth-providers/custom-oauth/custom_oauth_server.js","lineNumber":350,"sourceCode":"\t\t\t\tthrow new Meteor.Error('field_not_found', `Email field \"${this.emailField}\" not found in data`, data);\n\t\t\t}\n\t\t\treturn value;\n\t\t} catch (error) {\n\t\t\tthrow new Error('CustomOAuth: Failed to extract email', error.message);\n\t\t}\n\t}\n\n\tgetCustomName(data) {\n\t\ttry {\n\t\t\tconst value = fromTemplate(this.nameField, data);\n\n\t\t\tif (!value) {\n\t\t\t\treturn this.getName(data);\n\t\t\t}\n\n\t\t\treturn value;\n\t\t} catch (error) {\n\t\t\tthrow new Error('CustomOAuth: Failed to extract custom name', error.message);\n\t\t}\n\t}\n\n\tgetAvatarUrl(data) {\n\t\ttry {\n\t\t\tconst value = fromTemplate(this.avatarField, data);\n\n\t\t\tif (!value) {\n\t\t\t\tlogger.debug({ msg: 'Avatar field not found in data', avatarField: this.avatarField, data });\n\t\t\t}\n\t\t\treturn value;\n\t\t} catch (error) {\n\t\t\tthrow new Error('CustomOAuth: Failed to extract avatar url', error.message);\n\t\t}\n\t}\n\n\tgetName(identity) {\n\t\tconst name =","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/auth-providers/custom-oauth/custom_oauth_server.js#L332-L368","documentation":"getCustomName() maps nameField over the identity payload. Unlike username/e-mail, a missing value does not throw - it falls back to getName(), which tries name, username, nickname, CharacterName, userName, preferred_username and user.name in order. This error therefore means fromTemplate() itself threw: practically always an invalid regular expression inside a '{{/regex/::path}}' nameField (SyntaxError in new RegExp()), or nameField being undefined when the method is called directly.","triggerScenarios":"nameField set to '{{/(.+/::displayName}}' (unbalanced regex) so new RegExp throws during login; a template whose path portion triggers a TypeError; calling getCustomName on a strategy constructed without nameField.","commonSituations":"Admin reuses a username/avatar regex formula for the Name Field and breaks it; copy-paste introduces smart quotes or missing braces; provider payload change makes the path resolve against a primitive.","solutions":["Replace the nameField formula with a plain dot path that exists in the payload, e.g. 'display_name' or 'user.full_name'","If a regex is required, compile-check it first: new RegExp('<your regex>') must not throw, and it should have exactly one capture group","Clear Name Field to use the built-in fallback chain (name, username, nickname, CharacterName, userName, preferred_username, user.name)"],"exampleFix":"// before: Name Field = '{{/(.+/::displayName}}'  // unbalanced regex -> SyntaxError\n// Error: CustomOAuth: Failed to extract custom name ...\n\n// after: Name Field = 'display_name'","handlingStrategy":"validation","validationCode":"// compile-check a nameField formula before saving the OAuth config\nconst assertNameTemplateCompiles = (tpl: string) => {\n  const m = /^/((?!/::).*)/::(.+)/.exec(tpl);\n  if (m) new RegExp(m[1]); // throws SyntaxError now, not during everyone's login\n};","typeGuard":"const isValidNameTemplate = (tpl: string): boolean => {\n  try {\n    const m = /^/((?!/::).*)/::(.+)/.exec(tpl);\n    if (m) new RegExp(m[1]);\n    return true;\n  } catch {\n    return false;\n  }\n};","tryCatchPattern":"try {\n  identity.name = strategy.getCustomName(identity);\n} catch (error) {\n  logger.warn(error.message);\n  identity.name = strategy.getName(identity); // built-in fallback chain\n}","preventionTips":["Use plain dot paths for nameField unless a regex is essential","Test regex formulas with new RegExp() before saving","Remember the built-in fallback (name, username, nickname, ...) - often you do not need a custom mapping at all"],"tags":["oauth","custom-oauth","field-mapping","name","regex"],"backgroundTag":"oauth-identity-field-mapping-failed","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}