hcengineering/platform · critical · Error
KVS_URL env var is not set
Error message
KVS_URL env var is not set
What it means
In services/mail/pod-mail-worker/src/config.ts, kvsUrl is resolved by an inline IIFE that returns process.env.KVS_URL when defined and otherwise throws this error. KVS (key-value storage) access is mandatory for the mail worker, so the absence of KVS_URL aborts startup at import time.
Source
Thrown at services/mail/pod-mail-worker/src/config.ts:57
const config: Config = {
port: parseInt(process.env.PORT ?? '4050'),
secret: process.env.SECRET ?? 'secret',
accountsUrl: process.env.ACCOUNTS_URL ?? 'http://localhost:3000',
workspaceUrl: (() => {
if (process.env.WORKSPACE_URL !== undefined) {
return process.env.WORKSPACE_URL
}
throw Error('WORKSPACE_URL env var is not set')
})(),
ignoredAddresses: process.env.IGNORED_ADDRESSES?.split(',') ?? [],
hookToken: process.env.HOOK_TOKEN,
mailSizeLimit: process.env.MAIL_SIZE_LIMIT ?? '50mb',
storageConfig: process.env.STORAGE_CONFIG,
kvsUrl: (() => {
if (process.env.KVS_URL !== undefined) {
return process.env.KVS_URL
}
throw Error('KVS_URL env var is not set')
})(),
queueConfig: (() => {
if (process.env.QUEUE_CONFIG !== undefined) {
return process.env.QUEUE_CONFIG
}
throw Error('QUEUE_CONFIG env var is not set')
})(),
queueRegion: process.env.QUEUE_REGION ?? '',
communicationTopic: process.env.COMMUNICATION_TOPIC ?? 'hulygun',
serviceId: process.env.SERVICE_ID ?? 'huly-mail',
mailUrl: (() => {
if (process.env.MAIL_URL !== undefined) {
return process.env.MAIL_URL
}
throw Error('MAIL_URL env var is not set')
})(),
mailAuth: process.env.MAIL_AUTH ?? '',
footerMessage: process.env.FOOTER_MESSAGE ?? '<br><br><p>Sent via <a href="https://huly.io">Huly</a></p>',View on GitHub (pinned to 63e28dc964)
Solutions
- Set KVS_URL to the key-value storage service endpoint in the mail worker environment.
- Confirm the KVS service is deployed and reachable from the worker's network.
- Include KVS_URL in the local .env used for development runs.
- Check the deployment secret/ConfigMap actually mounts KVS_URL into the container env.
Example fix
// before KVS_URL unset -> throw at import // after # .env KVS_URL=http://kvs:3333
Defensive patterns
Strategy: validation
Validate before calling
const required = ['KVS_URL', 'WORKSPACE_URL', 'QUEUE_CONFIG', 'MAIL_URL'];
const missing = required.filter((k) => process.env[k] === undefined);
if (missing.length) {
console.error('Missing mail-worker env vars:', missing.join(', '));
process.exit(1);
}
new URL(process.env.KVS_URL!); Type guard
function isDefined<T>(v: T | undefined): v is T {
return v !== undefined;
} Try / catch
try {
const { default: config } = await import('./src/config.js');
} catch (e) {
if ((e as Error).message === 'KVS_URL env var is not set') {
console.error('Configure KVS_URL pointing to the key-value storage service');
}
process.exit(1);
} Prevention
- Inject KVS_URL from the same source that deploys the KVS service (consistent DNS/name).
- Ping the KVS endpoint as part of startup health checks.
- Document KVS_URL in the service deployment README.
When it happens
Trigger: process.env.KVS_URL is undefined when config.ts is first imported. Empty string passes this check (only `!== undefined` is tested).
Common situations: KVS endpoint not injected into the pod's env; storage infra renamed/moved and KVS_URL removed; running the worker locally without the KVS portion of the .env.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Invalid storage config:${st}
- Missing config for attributes: ${missingEnv.join(', ')}
- Missing config for attributes: ${missingEnv.join(', ')}
- Missing env variables: ${missingEnv.join(', ')}
- Missing env variables: ${missingEnv.join(', ')}
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/c5dd1d0e0b759144.
Report an issue: GitHub.