can1357/oh-my-pi · error · SearchProviderError

parallel: err.message (dynamic; thrown as SearchProviderErro

Error message

parallel: err.message (dynamic; thrown as SearchProviderError("parallel", err.message, err.statusCode))

What it means

searchParallel catches a ParallelApiError from the Parallel web-search API, first offering it to a shared HTTP-error classifier (classifyProviderHttpError) and, if unclassified, re-wrapping the upstream message and status code in a SearchProviderError tagged with provider "parallel". This normalizes provider failures so callers of the aggregate search get one consistent error type regardless of which backend failed. The message is dynamic: it is whatever the Parallel API returned.

Source

Thrown at packages/coding-agent/src/web/search/providers/parallel.ts:171

				fetch: params.fetch,
			},
			authStorage,
			sessionId,
			sourcePolicy,
		);

		return {
			provider: "parallel",
			sources: toSearchSources(result.sources, numResults),
			requestId: result.requestId,
		};
	} catch (err) {
		if (err instanceof ParallelApiError) {
			if (typeof err.statusCode === "number") {
				const classified = classifyProviderHttpError("parallel", err.statusCode, err.message);
				if (classified) throw classified;
			}
			throw new SearchProviderError("parallel", err.message, err.statusCode);
		}
		throw err;
	}
}

export class ParallelProvider extends SearchProvider {
	readonly id = "parallel";
	readonly label = "Parallel";

	isAvailable(authStorage: AuthStorage) {
		return !!getEnvApiKey("parallel") || authStorage.hasAuth("parallel");
	}

	search(params: SearchParams): Promise<SearchResponse> {
		return searchParallel(
			{
				query: params.query,
				num_results: params.numSearchResults ?? params.limit,

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the err.statusCode and message to identify the upstream cause (auth vs rate limit vs server error)
  2. If auth-related, verify the Parallel API key is set and valid
  3. If 429, back off and retry after the rate-limit window
  4. Check the Parallel status page if statusCode >= 500

Example fix

// before
const r = await search({ provider: "parallel", query: q });
// after
try {
  const r = await search({ provider: "parallel", query: q });
} catch (err) {
  if (err instanceof SearchProviderError && err.provider === "parallel") {
    // inspect err.statusCode (401 -> fix key, 429 -> backoff)
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!process.env.PARALLEL_API_KEY) throw new Error('Parallel search requires PARALLEL_API_KEY');

Type guard

function isSearchProviderError(e: unknown): e is SearchProviderError {
  return e instanceof SearchProviderError;
}

Try / catch

try {
  const res = await search({ provider: "parallel", query });
} catch (err) {
  if (err instanceof SearchProviderError && err.provider === "parallel") {
    if (err.statusCode === 429) await backoffAndRetry();
    else if (err.statusCode === 401) fixCredentials();
    else fallbackProvider();
  } else throw err;
}

Prevention

When it happens

Trigger: Any HTTP error response from the Parallel Search API (searchParallel, invoked via search/result) whose status is not already mapped by classifyProviderHttpError — e.g. 401 invalid key, 429 rate limit, 5xx outage, or a malformed request the API rejects.

Common situations: Expired or missing PARALLEL_API_KEY, exceeded requests-per-minute quota, Parallel-side incidents, invalid query parameters (bad domain filter, oversized numResults).

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/a2b3bf1a484517f0. Report an issue: GitHub.