koala73/worldmonitor · error · ValidationError
Provide ticker or company
Error message
Provide ticker or company
What it means
listCompanySignals throws ValidationError (field 'company') when both req.company and req.ticker are empty after trimming. As with its sibling enrichment endpoint, the v1 domain contract is preserved: a request carrying the deprecated domain field returns an empty stub response and never throws this error.
Source
Thrown at server/worldmonitor/intelligence/v1/list-company-signals.ts:64
'4.02': 'Restatement',
'5.01': 'Control Change',
'5.02': 'Executive Change',
};
export async function listCompanySignals(
_ctx: ServerContext,
req: ListCompanySignalsRequest,
): Promise<ListCompanySignalsResponse> {
const company = req.company?.trim();
const domain = req.domain?.trim().toLowerCase();
const ticker = req.ticker?.trim();
// Preserve the disabled v1 domain contract. Domain-derived attribution is
// still forbidden; callers using that deprecated field get an empty stub.
if (domain) return emptyResponse(company || '', false, domain);
if (!company && !ticker) {
throw new ValidationError([{ field: 'company', description: 'Provide ticker or company' }]);
}
const resolution = await resolveCompany({ ticker, name: company });
if (resolution.status !== 'ok') {
// "not_found" is a real, cacheable answer; "registry_unavailable" is a
// lookup failure and must not be cached as one.
return emptyResponse(
company || ticker?.toUpperCase() || '',
resolution.status === 'registry_unavailable',
);
}
const resolved = resolution.company;
const [submissions, news] = await Promise.all([
fetchSecSubmissions(resolved.cik),
fetchCompanyNewsMentions(resolved.ticker, resolved.name),
]);
View on GitHub (pinned to eeab0a219f)
Solutions
- Validate that company or ticker is present (and non-blank) before invoking the RPC
- When resolving from user text, put it in company (name resolution) or ticker, and skip blank rows
- Check the field names against the proto — 'name' sent instead of 'company' leaves both empty and triggers this
Defensive patterns
Strategy: validation
Validate before calling
const company = req.company?.trim(); const ticker = req.ticker?.trim(); if (!company && !ticker) return skipRow(row); // e.g. watchlist row without identifiers
Type guard
function isMissingCompanyViolation(body: unknown): boolean {
const v = (body as { violations?: { field?: string; description?: string }[] })?.violations;
return Array.isArray(v) && v.some((x) => x.field === 'company' && x.description === 'Provide ticker or company');
} Try / catch
try {
await listCompanySignals({ company, ticker });
} catch (e) {
if (e instanceof HttpError && e.status === 400 && isMissingCompanyViolation(e.body)) {
return promptForCompany();
}
throw e;
} Prevention
- Filter blank rows out of batch/watchlist syncs before calling the RPC
- Use the exact proto field names ('company', not 'name'/'q') so values are not silently dropped
- Remember domain-only requests return an empty stub by v1 contract — they never hit this error
When it happens
Trigger: Calling /api/intelligence/v1/list-company-signals with neither company nor ticker; whitespace-only values for both; a watchlist sync that includes rows with no identifiers.
Common situations: Empty search box submitted from a UI; batch job iterating company records where some rows lack both fields; parameter name confusion (sending 'name' or 'q' instead of 'company'/'ticker').
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
- At least one of domain or country is required
- query is required
- forms must be a comma-separated form list such as "8-K" or "
- start_date must be YYYY-MM-DD
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/4d7f61ab6304d130.
Report an issue: GitHub.