eyaltoledano/claude-task-master · error · TaskMasterError
API_ERROR
API_ERROR
Error message
`Failed to fetch organizations: ${error.message}` What it means
Thrown by OrganizationService.getOrganizations when the Supabase query against the user_accounts view returns an error object. The raw Supabase/Postgres error message is embedded in the thrown TaskMasterError, with code API_ERROR and context {operation:'getOrganizations'}. It signals a database/API-level failure (schema, RLS, or network), not an empty result set.
Source
Thrown at packages/tm-core/src/modules/auth/services/organization.service.ts:69
constructor(private supabaseClient: SupabaseClient<Database>) {}
/**
* Get all organizations for the authenticated user
*/
async getOrganizations(): Promise<Organization[]> {
try {
// The user is already authenticated via the Authorization header
// Query the user_accounts view/table (filtered by RLS for current user)
const { data, error } = await this.supabaseClient
.from('user_accounts')
.select(`
id,
name,
slug
`);
if (error) {
throw new TaskMasterError(
`Failed to fetch organizations: ${error.message}`,
ERROR_CODES.API_ERROR,
{ operation: 'getOrganizations' },
error
);
}
if (!data || data.length === 0) {
this.logger.debug('No organizations found for user');
return [];
}
// Map to our Organization interface
return data.map((org) => ({
id: org.id ?? '',
name: org.name ?? '',
slug: org.slug ?? org.id ?? '' // Use ID as fallback if slug is null
}));View on GitHub (pinned to c0c98d367c)
Solutions
- Read error.cause (the embedded Supabase error) for the exact Postgres/RLS message
- Re-authenticate to refresh an expired JWT, then retry
- Check the user_accounts view exists in the current schema (migrations may have renamed it)
- Verify network connectivity / Supabase project status
- If RLS-related, confirm the user has an active user_accounts row (account membership)
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight session check before querying organizations
const { data: sessionData, error: sessionErr } = await supabase.auth.getSession();
if (sessionErr || !sessionData.session) {
throw new Error('Not authenticated: run `tm auth login` before fetching organizations');
} Type guard
function isTaskMasterApiError(e: unknown): e is TaskMasterError {
return e instanceof TaskMasterError && e.code === ERROR_CODES.API_ERROR;
} Try / catch
try {
const orgs = await orgService.getOrganizations();
} catch (e) {
if (isTaskMasterApiError(e)) {
const cause = e.cause as { code?: string; message?: string };
if (cause?.code === '42P01') console.error('user_accounts view missing — schema out of date');
else if (cause?.code === '42501') console.error('RLS denied access — check account membership');
else console.error('Fetch organizations failed:', cause?.message ?? e.message);
} else throw e;
} Prevention
- Refresh the auth session before long-running operations
- Validate the user has at least one account membership before querying
- Run schema migrations in sync with the client's expected view/table names
- Check network reachability of the Supabase host before batch operations
- Inspect error.cause (the raw Supabase error) rather than only the top-level message
When it happens
Trigger: Calling getOrganizations() when the user_accounts table/view does not exist or was renamed, RLS denies access to the current user, the JWT/session is expired or invalid, or the Supabase request fails (network error, 5xx).
Common situations: Expired auth token after idle time; server schema migration renamed user_accounts; user's membership rows deleted so RLS rejects; offline or corporate proxy blocking the Supabase host.
Related errors
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/3f00635cdae030b0.
Report an issue: GitHub.