eyaltoledano/claude-task-master · error · TaskMasterError
NO_BRIEF_SELECTED
NO_BRIEF_SELECTED
Error message
No brief context found for watching. Please connect to a brief first.
What it means
TaskMasterError with code NO_BRIEF_SELECTED thrown by ApiStorage.watch when AuthManager's context has no briefId. Real-time watching is scoped to a brief, so without a connected brief the adapter refuses to start a watcher instead of watching nothing.
Source
Thrown at packages/tm-core/src/modules/storage/adapters/api-storage.ts:965
/**
* Watch for changes to tasks via Supabase Realtime
* Subscribes to postgres_changes for the tasks table filtered by brief_id
*
* Optional debouncing is supported for collaborative scenarios where multiple
* rapid changes (e.g., bulk operations, multiple users) could cause UI flicker.
* Default: 300ms (higher than FileStorage's 100ms since Realtime events are cleaner)
*/
async watch(
callback: (event: WatchEvent) => void,
options?: WatchOptions
): Promise<WatchSubscription> {
await this.ensureInitialized();
const authManager = AuthManager.getInstance();
const context = authManager.getContext();
if (!context?.briefId) {
throw new TaskMasterError(
'No brief context found for watching. Please connect to a brief first.',
ERROR_CODES.NO_BRIEF_SELECTED,
{ operation: 'watch' }
);
}
const supabase = authManager.supabaseClient.getClient();
const channelName = `tasks-watch-${context.briefId}-${Date.now()}`;
const debounceMs = options?.debounceMs ?? 300;
let debounceTimer: NodeJS.Timeout | undefined;
let closed = false;
const debouncedCallback = () => {
if (closed) return;
if (debounceTimer) {
clearTimeout(debounceTimer);
}View on GitHub (pinned to c0c98d367c)
Solutions
- Connect to a brief first (the auth/connect flow that populates AuthManager context with briefId), then call watch.
- Check AuthManager.getInstance().getContext()?.briefId before calling watch and short-circuit with a friendly prompt.
- Re-authenticate if the session expired and the brief context was lost.
- In CI/automation, ensure brief selection is configured via env/config before any watch call.
Example fix
// before
const watcher = await storage.watch(cb); // throws NO_BRIEF_SELECTED
// after
const ctx = AuthManager.getInstance().getContext();
if (!ctx?.briefId) {
await connectToBrief(briefId); // sets auth context
}
const watcher = await storage.watch(cb); Defensive patterns
Strategy: validation
Validate before calling
import { AuthManager } from '@tm/core';
const ctx = AuthManager.getInstance().getContext();
if (!ctx?.briefId) {
throw new Error('No brief connected. Run the connect flow before watch().');
} Type guard
function hasBriefContext(ctx: { briefId?: string } | null | undefined): ctx is { briefId: string } {
return typeof ctx?.briefId === 'string' && ctx.briefId.length > 0;
} Try / catch
try {
const watcher = await storage.watch(onChange);
} catch (e) {
if ((e as TaskMasterError).code === 'NO_BRIEF_SELECTED') {
await promptBriefSelection(); // interactive or env-based connect
return;
}
throw e;
} Prevention
- Always run the brief connect/auth flow before enabling watchers.
- In CI, supply brief selection via env/config and assert it at startup.
- Re-check the brief context after re-authentication, since expiry can drop it.
- Check error code NO_BRIEF_SELECTED specifically to distinguish config issues from network failures.
When it happens
Trigger: Calling storage.watch() (or watch on a collection) before authenticating, after authentication but without connecting/selecting a brief, or after the stored auth context was cleared/expired so context?.briefId is undefined.
Common situations: CLI/automation started fresh without a prior 'connect to brief' step, CI job missing the brief-selection env/config, a logged-out or expired session dropping the brief context, or running watch in a code path that never sets up AuthManager context.
Related errors
- NO_ORGANIZATIONS
- MISSING_ACCOUNT
- NO_BRIEF_SELECTED
- CONFIG_MISSING
- getInstance called with config after initialization; config
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/8c3f99603032cd14.
Report an issue: GitHub.