koala73/worldmonitor · error · ConvexError
INVALID_NAME
INVALID_NAME
Error message
INVALID_NAME
What it means
Thrown by createApiKey when args.name, after trimming whitespace, is empty. The name is a required human-readable label for the key and must contain at least one non-whitespace character. This is a client-side validation failure caught server-side as the last defense.
Source
Thrown at convex/apiKeys.ts:78
!entitlement ||
entitlement.validUntil < Date.now() ||
!entitlement.features.apiAccess
) {
throw new ConvexError("API_ACCESS_REQUIRED");
}
const scopes = normalizeCompanyMonitoringScopes(args.scopes);
// Issuing a scoped key is a first-use entry point, so it provisions the
// root. Requesting no scopes must stay entirely off Company Monitoring.
const companyMonitoringAccount = scopes
? await ensureActiveAccount(ctx, userId, entitlement)
: null;
if (scopes && !companyMonitoringAccount) {
throw new ConvexError("COMPANY_MONITORING_ACCESS_DENIED");
}
if (!args.name.trim()) {
throw new ConvexError("INVALID_NAME");
}
if (!/^wm_[a-f0-9]{5}$/.test(args.keyPrefix)) {
throw new ConvexError("INVALID_PREFIX");
}
if (!/^[a-f0-9]{64}$/.test(args.keyHash)) {
throw new ConvexError("INVALID_HASH");
}
// Enforce per-user key limit (count only non-revoked keys).
//
// API keys intentionally reject at the cap instead of silently rotating a
// valid key. If a prior race left too many active rows, converge by
// revoking enough oldest overflow rows to make room for this create.
const existing = await ctx.db
.query("userApiKeys")
.withIndex("by_userId", (q) => q.eq("userId", userId))
.collect();
const active = existing.filter((k) => !k.revokedAt);View on GitHub (pinned to ffec79ac33)
Solutions
- Trim and validate the name client-side before calling createApiKey — reject empty/whitespace-only values.
- Ensure the form input for key name is marked required and validated on submit.
- Pass args.name.trim() result only if non-empty.
Example fix
// before
await createApiKey(ctx, { name: " ", keyPrefix, keyHash });
// after
const name = userInput.trim();
if (!name) throw new Error("Name required");
await createApiKey(ctx, { name, keyPrefix, keyHash }); Defensive patterns
Strategy: validation
Validate before calling
const name = (args.name ?? "").trim();
if (!name) throw new Error("Name is required before calling createApiKey");
await createApiKey(ctx, { name, keyPrefix, keyHash }); Type guard
function isValidKeyName(name: unknown): name is string {
return typeof name === "string" && name.trim().length > 0;
} Try / catch
try {
await createApiKey(ctx, { name, keyPrefix, keyHash });
} catch (e) {
if (e instanceof ConvexError && e.message === "INVALID_NAME") {
// prompt user for a name
} else throw e;
} Prevention
- Make the name input required and validated in the UI form.
- Trim whitespace client-side and reject empty before submitting.
- Run a unit test on the createApiKey form for empty-name rejection.
When it happens
Trigger: Calling createApiKey with name="", name=" " (all whitespace), or name passed as an empty string from a form field that was not validated before submission.
Common situations: A UI form submitted the key-creation request without populating the name field; a test fixture or script passed an empty name; whitespace-only input from copy-paste that the client failed to trim and reject.
Related errors
- INVALID_PREFIX
- INVALID_HASH
- INVALID_API_KEY_SCOPES
- [initRamp] rampCurve entries must be positive integers
- get_intel_timeline requires at least one of domain ("conflic
AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12).
Data as JSON: /api/errors/16fec37068082aec.
Report an issue: GitHub.