{"record":{"id":"d08a90a2b7043b40","repo":"hcengineering/platform","slug":"invalid-storage-config-st","errorCode":null,"errorMessage":"Invalid storage config:${st}","messagePattern":"Invalid storage config:(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"foundations/server/packages/server-storage/src/starter.ts","lineNumber":46,"sourceCode":"  const storageConfig: StorageConfiguration = { default: '', storages: [] }\n\n  const storageEnv = configEnv ?? process.env.STORAGE_CONFIG\n  if (storageEnv !== undefined) {\n    parseStorageEnv(storageEnv, storageConfig)\n  }\n\n  if (storageConfig.storages.length === 0 || storageConfig.default === '') {\n    // 'STORAGE_CONFIG is required for complex configuration, fallback to minio config'\n    addMinioFallback(storageConfig)\n  }\n  return storageConfig\n}\n\nexport function parseStorageEnv (storageEnv: string, storageConfig: StorageConfiguration): void {\n  const storages = storageEnv.split(';')\n  for (const st of storages) {\n    if (st.trim().length === 0 || !st.includes('|')) {\n      throw new Error('Invalid storage config:' + st)\n    }\n    let [kindName, url] = st.split('|')\n    let [kind, name] = kindName.split(',')\n    if (name == null) {\n      name = kind\n    }\n    let hasProtocol = true\n    if (!url.includes('://')) {\n      // No protocol, add empty one\n      url = 'empty://' + url\n      hasProtocol = false\n    }\n    const uri = new URL(url)\n    const config: StorageConfig = {\n      kind,\n      name,\n      endpoint: (hasProtocol ? uri.protocol + '//' : '') + uri.hostname, // Port should go away\n      port: uri.port !== '' ? parseInt(uri.port) : undefined","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/server-storage/src/starter.ts#L28-L64","documentation":"parseStorageEnv splits the STORAGE_CONFIG environment variable on ';' and validates each entry. If an entry is empty after trim or contains no '|' separator, it throws Error('Invalid storage config:' + st). The expected per-entry format is kind(,name)?|uri|contentTypes — so this error means a syntactically malformed STORAGE_CONFIG value, not a connectivity problem.","triggerScenarios":"Starting a server with STORAGE_CONFIG containing a stray/empty segment (e.g. a trailing ';', a newline kept inside an entry after whitespace-only trim, or an entry like 'minio|minio:9000' missing the '|' split — most commonly a value where segments were joined without ';' or with wrong characters like ',' between entries).","commonSituations":"Paste errors when editing docker-compose/k8s env values; shell line continuations introducing blank segments; quoting issues where the whole variable collapsed into one malformed entry; upgrading from a single-URI config format to the multi-storage ';'-separated format without reformatting.","solutions":["Print and inspect STORAGE_CONFIG exactly as the process sees it (echo or k8s describe) and check for trailing/empty ';'-separated segments","Ensure every entry matches kind(,name)?|uri|contentTypes with '|' separating kind and URI","Remove trailing semicolons and embedded newlines (the parser only ignores newlines in comments, not stray blanks in your value)","Use the documented example format from starter.ts as a template and restart"],"exampleFix":"// before\nSTORAGE_CONFIG=\"minio|minio:9000?accessKey=minio&secretKey=minio;\"\n// after\nSTORAGE_CONFIG=\"minio|minio:9000?accessKey=minio&secretKey=minio\"","handlingStrategy":"validation","validationCode":"function validateStorageEnv (storageEnv: string): void {\n  const entries = storageEnv.split(';')\n  for (const st of entries) {\n    if (st.trim().length === 0 || !st.includes('|')) {\n      throw new Error(`Invalid storage config: ${st}`)\n    }\n  }\n}\n// call before server start\nvalidateStorageEnv(process.env.STORAGE_CONFIG ?? '')","typeGuard":"function isValidStorageEntry (st: string): boolean {\n  return st.trim().length > 0 && st.includes('|')\n}","tryCatchPattern":"try {\n  parseStorageEnv(storageEnv, storageConfig)\n} catch (err) {\n  console.error('STORAGE_CONFIG is malformed:', (err as Error).message)\n  process.exit(1)\n}","preventionTips":["Lint STORAGE_CONFIG format in CI (each entry: kind(,name)?|uri|contentTypes)","Avoid trailing semicolons and raw newlines in env values","Use single-quoted heredocs in compose/k8s to prevent shell mangling","Log the parsed entry count at startup to confirm the config loaded fully"],"tags":["configuration","environment","storage","parsing"],"backgroundTag":"invalid-storage-config","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}