can1357/oh-my-pi · error · SearchProviderError
Every credential-free engine is excluded by settings.
Error message
Every credential-free engine is excluded by settings.
What it means
The Public Web aggregate fans out to a fixed set of credential-free engines (startpage, google, duckduckgo, ecosia, mojeek). If settings exclude every one of them, there is nothing to fan out to, so searchPublicWeb throws a SearchProviderError (status 400) before making any network calls.
Source
Thrown at packages/coding-agent/src/web/search/providers/public.ts:126
* The fan-out races three exits and returns at the earliest: every engine
* settled; the soft deadline elapsed with at least one success in hand; the
* hard deadline elapsed regardless. If the soft deadline fires before any
* engine has delivered, the aggregate keeps waiting (up to the hard cap) for
* the first success, so a slow field degrades to fewer engines rather than
* an empty answer. Stragglers are aborted once the race resolves. Individual
* engine failures (bot challenges, timeouts) are tolerated; the call fails
* only when every engine fails.
*/
export async function searchPublicWeb(
params: SearchParams,
deadlines: PublicWebDeadlines = {},
): Promise<SearchResponse> {
const softMs = deadlines.softMs ?? SOFT_DEADLINE_MS;
const hardMs = deadlines.hardMs ?? HARD_DEADLINE_MS;
const numResults = clampNumResults(params.numSearchResults ?? params.limit, DEFAULT_NUM_RESULTS, MAX_NUM_RESULTS);
const engineIds = PUBLIC_ENGINE_IDS.filter(id => !isSearchProviderExcluded(id));
if (engineIds.length === 0) {
throw new SearchProviderError("public", "Every credential-free engine is excluded by settings.", 400);
}
// Each engine composes its own per-request ceiling on top of the shared
// hard deadline; the straggler controller lets the aggregate cancel
// still-running engines once it decides to return.
const straggler = new AbortController();
const signal = AbortSignal.any([withHardTimeout(params.signal, params.timeoutMs), straggler.signal]);
const responses: (SearchResponse | undefined)[] = new Array(engineIds.length);
const failures: { provider: { id: SearchProviderId; label: string }; error: unknown }[] = [];
const firstSuccess = Promise.withResolvers<void>();
const all = Promise.all(
engineIds.map(async (id, index) => {
try {
const provider = await getSearchProvider(id);
responses[index] = await provider.search({ ...params, signal });
firstSuccess.resolve();
} catch (error) {View on GitHub (pinned to 9690622007)
Solutions
- Re-enable at least one credential-free engine in settings (remove it from the exclusion list)
- Inspect search provider exclusion settings for overly broad entries
- Switch the search call to a credentialed provider (Perplexity, Parallel) instead of the public aggregate
Example fix
// before (settings)
{ "search": { "excludeProviders": ["startpage","google","duckduckgo","ecosia","mojeek"] } }
// after
{ "search": { "excludeProviders": ["ecosia"] } } Defensive patterns
Strategy: validation
Validate before calling
import { isSearchProviderExcluded } from "./web/search/provider";
const engines = ["startpage","google","duckduckgo","ecosia","mojeek"];
if (engines.every(id => isSearchProviderExcluded(id))) {
throw new Error('Enable at least one credential-free engine before public web search');
} Try / catch
try {
return await searchPublicWeb(params);
} catch (err) {
if (err instanceof SearchProviderError && err.statusCode === 400 && err.message.includes("excluded by settings")) {
return credentialedProviderSearch(params);
}
throw err;
} Prevention
- Never exclude every engine in the credential-free set
- Audit copied settings templates for wholesale exclusion lists
- Keep one default engine always enabled
When it happens
Trigger: Calling the public web search while every PUBLIC_ENGINE_IDS entry is excluded via provider exclusion settings (isSearchProviderExcluded returns true for all five).
Common situations: User disabled individual engines after bot-challenge complaints and accidentally excluded all of them; a config template copied exclusion lists verbatim; settings file listing all engines under an exclusion key.
Related errors
- vault:// is disabled. Enable it by setting `vault.enabled =
- Agent "${agentName}" is disabled in settings. Enable it via
- Subagent isolated execution requires task.isolation.mode to
- URL reads are disabled by settings.
- Image submission is disabled by settings (images.blockImages
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c23d33ad8dceffaa.
Report an issue: GitHub.