koala73/worldmonitor · critical · ConvexError
COMPANY_MONITORING_WORKER_UNAUTHORIZED
Error message
COMPANY_MONITORING_WORKER_UNAUTHORIZED
What it means
Thrown by requireWorkerSecret when the provided worker secret does not match the COMPANY_MONITORING_WORKER_SECRET environment variable (compared with a timing-safe SHA-256 comparison), or when that environment variable is unset/empty. This gates all worker-facing mutations so only trusted workers holding the secret can claim work or finalize results.
Source
Thrown at convex/companyMonitoring/orchestration.ts:211
async function timingSafeEqualStrings(left: string, right: string): Promise<boolean> {
const encoder = new TextEncoder();
const [leftDigest, rightDigest] = await Promise.all([
crypto.subtle.digest("SHA-256", encoder.encode(left)),
crypto.subtle.digest("SHA-256", encoder.encode(right)),
]);
const leftBytes = new Uint8Array(leftDigest);
const rightBytes = new Uint8Array(rightDigest);
let mismatch = 0;
for (let index = 0; index < leftBytes.length; index += 1) {
mismatch |= leftBytes[index]! ^ rightBytes[index]!;
}
return mismatch === 0;
}
async function requireWorkerSecret(secret: string): Promise<void> {
const expected = process.env.COMPANY_MONITORING_WORKER_SECRET ?? "";
if (!expected || !(await timingSafeEqualStrings(secret, expected))) {
throw new ConvexError("COMPANY_MONITORING_WORKER_UNAUTHORIZED");
}
}
function providerRolloutEnabled(source: Source): boolean {
const flags: Record<Source, boolean> = {
exa: COMPANY_MONITORING_ROLLOUT_FLAGS.exaProvider,
x: COMPANY_MONITORING_ROLLOUT_FLAGS.xProvider,
};
return flags[source];
}
function enabledSources(): Source[] {
return (["exa", "x"] as const).filter(providerRolloutEnabled);
}
function requireProviderClaimPolicy(
account: Doc<"companyMonitoringAccounts">,
source: Source,View on GitHub (pinned to ffec79ac33)
Solutions
- Set COMPANY_MONITORING_WORKER_SECRET in the Convex deployment environment to a strong shared value.
- Configure the worker to send the same secret and rotate both ends together.
- Verify the secret is present via the deployment dashboard (never log its value).
Example fix
// before — secret missing from Convex env, worker unauthorized // after # set in Convex deployment (do not commit the value) npx convex env set COMPANY_MONITORING_WORKER_SECRET=<strong-random-secret> # then configure the worker with the identical secret
Defensive patterns
Strategy: validation
Validate before calling
// ensure the env var is set and the worker sends the same secret
if (!process.env.COMPANY_MONITORING_WORKER_SECRET) {
throw new Error("COMPANY_MONITORING_WORKER_SECRET not deployed");
} Try / catch
try { await workerMutation(...); }
catch (err) {
if (err instanceof ConvexError && err.message === "COMPANY_MONITORING_WORKER_UNAUTHORIZED") {
// halt worker and alert; do not retry with the same secret
} else throw err;
} Prevention
- Deploy COMPANY_MONITORING_WORKER_SECRET in the Convex environment.
- Rotate secret and worker config together.
- Verify by exit code/response, never by printing the secret.
When it happens
Trigger: Calling a worker-gated mutation without the secret, with the wrong secret, or when COMPANY_MONITORING_WORKER_SECRET is not configured in the Convex deployment.
Common situations: Secret not deployed to the Convex environment; worker using a stale secret after rotation; secret omitted from local dev config; secret leaked/mis-typed.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- INVALID_COMPANY_MONITORING_WORKER_ID
- COMPANY_MONITORING_ACCESS_DENIED
- [sendProLaunchBroadcast] RESEND_API_KEY not set
- INVALID_${field.toUpperCase()}
- COMPANY_MONITORING_ACCESS_DENIED
AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12).
Data as JSON: /api/errors/61a1793f52ea45e4.
Report an issue: GitHub.