koala73/worldmonitor · error · Error
${field} must be a string
Error message
${field} must be a string What it means
Contract validation error from assertPlainText in the shared company-monitoring contract: a text field expected to be a string is some other type (number, object, array, null). The offending field name is interpolated into the message. This is a caller-supplied payload bug, caught before any persistence.
Source
Thrown at shared/company-monitoring-contract.ts:80
const FILTER_HASH = /^[a-f0-9]{64}$/;
const RFC3339 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?Z$/;
const LOGICAL_ID_PREFIXES = {
company: 'cm_company_',
claim: 'cm_claim_',
event: 'cm_event_',
impact: 'cm_impact_',
evidence: 'cm_evidence_',
} as const;
const ULID = '[0-9A-HJKMNP-TV-Z]{26}';
const encoder = new TextEncoder();
function utf8Bytes(value: string): number {
return encoder.encode(value).byteLength;
}
function assertPlainText(value: unknown, field: string, maxBytes: number): string {
if (typeof value !== 'string') throw new Error(`${field} must be a string`);
const unicodeNormalized = value.normalize('NFC');
if (CONTROL_CHARACTERS.test(unicodeNormalized)) throw new Error(`${field} contains control characters`);
const normalized = unicodeNormalized.trim().replace(/\s+/g, ' ');
if (!normalized) throw new Error(`${field} is required`);
if (utf8Bytes(normalized) > maxBytes) throw new Error(`${field} exceeds ${maxBytes} bytes`);
return normalized;
}
function normalizeOptionalText(value: unknown, field: string, maxBytes: number): string | undefined {
if (value === undefined || value === null || value === '') return undefined;
return assertPlainText(value, field, maxBytes);
}
function normalizeList(
value: unknown,
field: string,
maxItems: number,
normalize: (item: unknown, index: number) => string,View on GitHub (pinned to eeab0a219f)
Solutions
- Send the named field as a JSON string, not a number, object, or array
- Check for client-side serialization mistakes (e.g. forgetting to stringify an identifier)
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at shared/company-monitoring-contract.ts:80 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/e2524d27badad25f.
Report an issue: GitHub.