Summary
Linear API calls return null on ANY error (404, 500, network timeout, auth failure) with no retry logic or error distinction.
Source
Adversarial Security Assessment
Location
impl/mvp/src/tools/linear-client.ts:303-306
impl/mvp/src/holons/root.ts:1504-1506
Current Behavior
// fetchIssue() returns null on any error
const parentIssue = await linearClient.fetchIssue(linearRef.issue_id);
if (!parentIssue) {
throw new Error(`Parent issue not found: ${linearRef.issue_id}`);
}
Problems
- No distinction between "not found" vs "service down"
- Transient failures (500, timeout) treated same as permanent (404)
- No retry for recoverable errors
- Users don't know if Linear is down
Impact
- Tasks fail silently on transient Linear outages
- No self-healing for network blips
- Poor observability
Severity
High | Likelihood: High (Linear is external service)
Recommended Fix
async function fetchWithRetry<T>(
operation: () => Promise<T>,
options: { maxRetries: number; baseDelayMs: number }
): Promise<T> {
for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
if (!isTransientError(error) || attempt === options.maxRetries) {
throw error;
}
const delay = options.baseDelayMs * Math.pow(2, attempt) * (0.5 + Math.random());
await sleep(delay);
}
}
throw new Error('Unreachable');
}
function isTransientError(error: unknown): boolean {
if (error instanceof HttpError) {
return error.status >= 500 || error.status === 429;
}
return error instanceof NetworkError;
}
Generated by HCA Architecture Assessment
Summary
Linear API calls return
nullon ANY error (404, 500, network timeout, auth failure) with no retry logic or error distinction.Source
Adversarial Security Assessment
Location
impl/mvp/src/tools/linear-client.ts:303-306impl/mvp/src/holons/root.ts:1504-1506Current Behavior
Problems
Impact
Severity
High | Likelihood: High (Linear is external service)
Recommended Fix
Generated by HCA Architecture Assessment