{"record":{"id":"39e1b9b82b9dd710","repo":"RocketChat/Rocket.Chat","slug":"service-not-configured-39e1b9","errorCode":null,"errorMessage":"Service not configured","messagePattern":"Service not configured","errorType":"exception","errorClass":"Accounts.ConfigError","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/auth-providers/oauth/oauth.js","lineNumber":39,"sourceCode":"\t}\n\n\tcheck(\n\t\toptions,\n\t\tMatch.ObjectIncluding({\n\t\t\tserviceName: String,\n\t\t}),\n\t);\n\n\tconst service = AccessTokenServices[options.serviceName];\n\n\t// Skip everything if there's no service set by the oauth middleware\n\tif (!service) {\n\t\tthrow new Error(`Unexpected AccessToken service ${options.serviceName}`);\n\t}\n\n\t// Make sure we're configured\n\tif (!(await ServiceConfiguration.configurations.findOneAsync({ service: options.serviceName }))) {\n\t\tthrow new Accounts.ConfigError();\n\t}\n\n\tif (!_.contains(Accounts.oauth.serviceNames(), service.serviceName)) {\n\t\t// serviceName was not found in the registered services list.\n\t\t// This could happen because the service never registered itself or\n\t\t// unregisterService was called on it.\n\t\treturn {\n\t\t\ttype: 'oauth',\n\t\t\terror: new Meteor.Error(Accounts.LoginCancelledError.numericError, `No registered oauth service found for: ${service.serviceName}`),\n\t\t};\n\t}\n\n\tconst oauthResult = await service.handleAccessTokenRequest(options);\n\n\treturn Accounts.updateOrCreateUserFromExternalService(service.serviceName, oauthResult.serviceData, oauthResult.options);\n});\n","sourceCodeStart":21,"sourceCodeEnd":56,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/auth-providers/oauth/oauth.js#L21-L56","documentation":"The Meteor login handler registered in oauth.js serves logins that pass { serviceName, accessToken, expiresIn } - the access-token login flow used by clients that already hold a provider token (mobile apps, deep links, API integrations). Before delegating to the registered AccessTokenService handler it verifies a ServiceConfiguration.configurations document exists for the serviceName; if not, it throws Accounts.ConfigError, whose rendered message is 'Service <name> not configured'. Note the neighbouring failures are distinct: an unknown serviceName throws 'Unexpected AccessToken service', an unregistered-but-configured service returns LoginCancelledError instead.","triggerScenarios":"A client calls login/Meteor.loginWithService-style flow with options.accessToken for a custom OAuth service whose admin configuration was never saved or was deleted from ServiceConfiguration.configurations; service disabled in admin before the token login attempt.","commonSituations":"Mobile/app integrations using token login against a workspace where the OAuth app row is missing; environment restore without the ServiceConfiguration collection; service name typo that still matches a registered handler but has no config row.","solutions":["Save the custom OAuth service credentials in Admin -> OAuth so the ServiceConfiguration document exists","Verify with db.ServiceConfiguration.configurations.findOne({ service: '<serviceName>' }) and re-create if missing","Ensure the service is enabled and the serviceName sent by the client matches the admin entry exactly","If you intended a different failure mode, distinguish it: unknown service name gives 'Unexpected AccessToken service', unregistered service gives LoginCancelledError"],"exampleFix":"// before: client sends { serviceName: 'my-idp', accessToken, expiresIn } with no config row\n// -> Error: Service my-idp not configured\n\n// after: admin saves My Idp credentials (writes ServiceConfiguration row), client retries the same call","handlingStrategy":"try-catch","validationCode":"// before attempting token login, verify the service is configured\nimport { ServiceConfiguration } from 'meteor/service-configuration';\n\nconst canLoginWithToken = async (serviceName: string): Promise<boolean> =>\n  !!(await ServiceConfiguration.configurations.findOneAsync({ service: serviceName }, { projection: { _id: 1 } }));\n\nif (!(await canLoginWithToken('my-idp'))) throw new Error('SSO service not configured; ask admin to save credentials');","typeGuard":null,"tryCatchPattern":"try {\n  const result = await Accounts.callLoginMethod({\n    methodArguments: [{ serviceName: 'my-idp', accessToken: token, expiresIn: 3600 }],\n  });\n} catch (error) {\n  if (/not configured/i.test(error.message)) {\n    // config row missing: surface an admin-facing message instead of retrying\n    showError('SSO is not configured on this workspace.');\n  } else {\n    throw error;\n  }\n}","preventionTips":["Seed/backup the ServiceConfiguration collection as part of deployment","Validate serviceName on the client before attempting token login","Distinguish this from 'Unexpected AccessToken service' (unregistered handler) when diagnosing"],"tags":["oauth","meteor","service-configuration","access-token","login"],"backgroundTag":"oauth-service-not-configured","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}