{"record":{"id":"46ad3bc27a7a92a6","repo":"hcengineering/platform","slug":"login-failed","errorCode":null,"errorMessage":"Login failed","messagePattern":"Login failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"foundations/core/packages/api-client/src/utils.ts","lineNumber":46,"sourceCode":"export async function getWorkspaceToken (\n  url: string,\n  options: AuthOptions,\n  config?: ServerConfig\n): Promise<WorkspaceToken> {\n  config ??= await loadServerConfig(url)\n\n  let token: string | undefined\n\n  if ('token' in options) {\n    token = options.token\n  } else {\n    const { email, password } = options\n    const loginInfo = await getAccountClient(config.ACCOUNTS_URL).login(email, password)\n    token = loginInfo.token\n  }\n\n  if (token === undefined) {\n    throw new Error('Login failed')\n  }\n\n  const ws = await getAccountClient(config.ACCOUNTS_URL, token).selectWorkspace(options.workspace)\n  if (ws === undefined) {\n    throw new Error('Workspace not found')\n  }\n\n  return { endpoint: ws.endpoint, token: ws.token, workspaceId: ws.workspace, info: ws }\n}\n","sourceCodeStart":28,"sourceCodeEnd":56,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/core/packages/api-client/src/utils.ts#L28-L56","documentation":"getWorkspaceToken resolves a workspace-scoped token by logging in (or using a provided token). After attempting login via the accounts client, if no token could be obtained, it throws 'Login failed'. This means credentials were missing or the login call returned no token.","triggerScenarios":"Calling getWorkspaceToken with options that lack a valid token and where login(email, password) returns undefined/no token — wrong email, wrong password, or account service unreachable/failing.","commonSituations":"Stale or mistyped credentials in env/config; disabled or deleted account; ACCOUNTS_URL pointing at the wrong service; accounts service returning 2xx with an unexpected payload shape.","solutions":["Verify email/password credentials are correct and the account exists.","Check config.ACCOUNTS_URL points to a running accounts service.","If passing a token directly, confirm options.token is defined and not expired.","Inspect the login() response shape — an API/version mismatch may drop the token field.","Wrap the call in try/catch and surface a clear credential/config error to the user."],"exampleFix":"// before\nconst { token } = await getWorkspaceToken({ email, password, workspace })\n// after\ntry {\n  const { token } = await getWorkspaceToken({ email, password, workspace })\n} catch (err) {\n  if (err.message === 'Login failed') {\n    throw new Error('Check ACCOUNTS_URL and account credentials: ' + err.message)\n  }\n  throw err\n}","handlingStrategy":"validation","validationCode":"if (options.token === undefined && (options.email === undefined || options.password === undefined)) {\n  throw new Error('getWorkspaceToken requires either a token or email+password')\n}","typeGuard":"function hasCredentials(o: { token?: string, email?: string, password?: string }): boolean {\n  return typeof o.token === 'string' || (typeof o.email === 'string' && typeof o.password === 'string')\n}","tryCatchPattern":"try {\n  const { token } = await getWorkspaceToken(opts)\n} catch (err) {\n  if (err.message === 'Login failed') {\n    showLoginDialog() // re-authenticate\n    return\n  }\n  throw err\n}","preventionTips":["Validate credential presence before calling getWorkspaceToken","Verify ACCOUNTS_URL points at the correct running service","Handle 'Login failed' by prompting re-authentication, not crashing","Keep account credentials out of client-side code in production"],"tags":["authentication","login","config"],"backgroundTag":"authentication-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}