hcengineering/platform · error · Error
Login failed
Error message
Login failed
What it means
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.
Source
Thrown at foundations/core/packages/api-client/src/utils.ts:46
export async function getWorkspaceToken (
url: string,
options: AuthOptions,
config?: ServerConfig
): Promise<WorkspaceToken> {
config ??= await loadServerConfig(url)
let token: string | undefined
if ('token' in options) {
token = options.token
} else {
const { email, password } = options
const loginInfo = await getAccountClient(config.ACCOUNTS_URL).login(email, password)
token = loginInfo.token
}
if (token === undefined) {
throw new Error('Login failed')
}
const ws = await getAccountClient(config.ACCOUNTS_URL, token).selectWorkspace(options.workspace)
if (ws === undefined) {
throw new Error('Workspace not found')
}
return { endpoint: ws.endpoint, token: ws.token, workspaceId: ws.workspace, info: ws }
}
View on GitHub (pinned to 63e28dc964)
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.
Example fix
// before
const { token } = await getWorkspaceToken({ email, password, workspace })
// after
try {
const { token } = await getWorkspaceToken({ email, password, workspace })
} catch (err) {
if (err.message === 'Login failed') {
throw new Error('Check ACCOUNTS_URL and account credentials: ' + err.message)
}
throw err
} Defensive patterns
Strategy: validation
Validate before calling
if (options.token === undefined && (options.email === undefined || options.password === undefined)) {
throw new Error('getWorkspaceToken requires either a token or email+password')
} Type guard
function hasCredentials(o: { token?: string, email?: string, password?: string }): boolean {
return typeof o.token === 'string' || (typeof o.email === 'string' && typeof o.password === 'string')
} Try / catch
try {
const { token } = await getWorkspaceToken(opts)
} catch (err) {
if (err.message === 'Login failed') {
showLoginDialog() // re-authenticate
return
}
throw err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Workspace not found
- Unable to determine the required version of Rush from ${RUSH
- Unable to find ${RUSH_JSON_FILENAME}.
- Workspace ${options.workspace} not found
- await response.text()
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/46ad3bc27a7a92a6.
Report an issue: GitHub.