koala73/worldmonitor · error · ApiError
At least one of domain or country is required
Error message
At least one of domain or country is required
What it means
getIntelTimeline throws ApiError 400 when, after validateHistoryScope normalization, both scope.domain and scope.country are empty. Normalization runs BEFORE this check specifically so a whitespace-only country cannot satisfy the 'at least one scope' requirement and then silently match nothing. The endpoint is premium-gated at the gateway, so callers reaching this error already passed entitlement.
Source
Thrown at server/worldmonitor/intelligence/v1/get-intel-timeline.ts:48
* (ApiError, surfaced by server/error-mapper.ts) tells the caller their
* request was wrong instead of blaming the backend. buf.validate cannot
* express "at least one of", so the check lives in code.
*
* A store failure returns an empty result with `upstreamUnavailable: true`
* rather than a 5xx, so the gateway does not cache an empty timeline for the
* slow tier's TTL. Premium-gated at the gateway via PREMIUM_RPC_PATHS +
* ENDPOINT_ENTITLEMENTS.
*/
export const getIntelTimeline: IntelligenceServiceHandler['getIntelTimeline'] = async (
_ctx: ServerContext,
req: GetIntelTimelineRequest,
): Promise<GetIntelTimelineResponse> => {
// Normalize BEFORE the scope check: a whitespace-only country would
// otherwise satisfy "at least one scope" and then match nothing.
const scope = validateHistoryScope(req, MAX_LIMIT);
const { domain, country } = scope;
if (!domain && !country) {
throw new ApiError(400, 'At least one of domain or country is required', '');
}
const limit = resolveLimit(scope.limit, DEFAULT_LIMIT, MAX_LIMIT);
const result = await cacheSuccessfulHistoryRead('timeline', {
domain, country, from: scope.from, to: scope.to, limit,
}, () => intelHistoryTimeline({ ...scope, limit }));
if (!result) {
return { records: [], partial: false, upstreamUnavailable: true };
}
return { records: result.records, partial: result.partial, upstreamUnavailable: false };
};
View on GitHub (pinned to eeab0a219f)
Solutions
- Supply a non-empty domain or country (or both) on every call
- Enforce the one-of rule in the client: if both filters are cleared, disable the request instead of submitting
- Trim scope inputs client-side so accidental whitespace-only values are caught early
Defensive patterns
Strategy: validation
Validate before calling
const domain = req.domain?.trim().toLowerCase();
const country = req.country?.trim();
if (!domain && !country) {
throw new ClientError('Timeline requires a domain or a country scope');
} Type guard
function isMissingScopeError(body: unknown): boolean {
return (body as { message?: string })?.message === 'At least one of domain or country is required';
} Try / catch
try {
await getIntelTimeline({ domain, country });
} catch (e) {
if (e instanceof HttpError && e.status === 400 && isMissingScopeError(e.body)) {
return disableSubmit('Choose a domain or country filter');
}
throw e;
} Prevention
- Disable timeline requests in the UI when both scope filters are cleared
- Trim scope inputs client-side — whitespace-only values count as absent server-side too
- Sending only from/to dates and limit never satisfies the scope requirement
When it happens
Trigger: Calling /api/intelligence/v1/get-intel-timeline with no domain and no country; sending country: ' ' (whitespace only) and nothing else; sending only from/to date range and limit, assuming dates alone scope the query.
Common situations: UI 'clear filters' action submits the form with every scope field emptied; API explorer request built without copying the scope parameter; client treats country as optional and domain as optional without enforcing one-of.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Provide ticker or name
- Provide ticker or company
- query is required
- get_intel_timeline requires at least one of domain ("conflic
- forms must be a comma-separated form list such as "8-K" or "
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/3939136f631e6ce4.
Report an issue: GitHub.