{"record":{"id":"fd3c92830c43d95e","repo":"hcengineering/platform","slug":"one-of-endpoint-accesskey-secretkey-values-are-not","errorCode":null,"errorMessage":"One of endpoint/accessKey/secretKey values are not specified","messagePattern":"One of endpoint/accessKey/secretKey values are not specified","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"foundations/server/packages/server-storage/src/starter.ts","lineNumber":86,"sourceCode":"    uri.searchParams.forEach((v, k) => {\n      ;(config as any)[k] = v\n    })\n\n    if (storageConfig.storages.find((it) => it.name === config.name) !== undefined) {\n      throw new Error(`Duplicated storage name ${config.name}, skipping config:${st}`)\n    }\n    storageConfig.storages.push(config)\n    storageConfig.default = config.name\n  }\n}\n\nexport function createStorageFromConfig (config: StorageConfig): StorageAdapter {\n  let adapter: StorageAdapter\n  const kind = config.kind\n  if (kind === MINIO_CONFIG_KIND) {\n    const c = config as MinioConfig\n    if (c.endpoint == null || c.accessKey == null || c.secretKey == null) {\n      throw new Error('One of endpoint/accessKey/secretKey values are not specified')\n    }\n    adapter = new MinioService(c)\n  } else if (kind === S3_CONFIG_KIND) {\n    const c = config as S3Config\n    if (c.endpoint == null || c.accessKey == null || c.secretKey == null) {\n      throw new Error('One of endpoint/accessKey/secretKey values are not specified')\n    }\n    adapter = new S3Service(c)\n  } else if (kind === DATALAKE_CONFIG_KIND) {\n    const c = config as DatalakeConfig\n    if (c.endpoint == null) {\n      throw new Error('Endpoint value is not specified')\n    }\n    adapter = new DatalakeService(c)\n  } else if (kind === HULYLAKE_CONFIG_KIND) {\n    const c = config as HulylakeConfig\n    if (c.endpoint == null) {\n      throw new Error('Endpoint value is not specified')","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/server-storage/src/starter.ts#L68-L104","documentation":"createStorageFromConfig validates MinIO configs before constructing MinioService: endpoint, accessKey and secretKey must all be present. If any is null/undefined it throws 'One of endpoint/accessKey/secretKey values are not specified'. Since endpoint/port come from the URI and accessKey/secretKey come from query parameters of the STORAGE_CONFIG entry, this means the minio entry is incomplete.","triggerScenarios":"A minio STORAGE_CONFIG entry lacking &accessKey= or &secretKey= query params, or an empty endpoint (malformed URI part) — hit at startup via storageAdapter/buildStorageFromConfig when kind === 'minio'.","commonSituations":"Env var interpolation leaving ${ACCESS_KEY} empty in the composed STORAGE_CONFIG; secrets not mounted/injected in k8s so query params end up undefined; typo in param names (accesskey/secretkey case sensitivity); Docker compose variable not exported so it expands to nothing.","solutions":["Check the minio entry of STORAGE_CONFIG includes endpoint host, accessKey and secretKey query parameters","Verify the source environment variables (e.g. MINIO_ACCESS_KEY/SECRET_KEY) are actually set where the server runs — an unset var interpolates to an empty string","Fix param-name casing to exactly accessKey and secretKey","For local dev, use the fallback path: leave STORAGE_CONFIG unset so storageConfigFromEnv adds addMinioFallback with minio/minio defaults"],"exampleFix":"// before\nSTORAGE_CONFIG=minio|minio:9000?accessKey=${MINIO_ACCESS_KEY}&secretKey=${MINIO_SECRET_KEY}\n// (MINIO_SECRET_KEY unset -> empty)\n// after: ensure vars are exported\nexport MINIO_SECRET_KEY=miniosecret","handlingStrategy":"validation","validationCode":"function validateMinioConfig (c: Partial<MinioConfig>): void {\n  const missing = (['endpoint', 'accessKey', 'secretKey'] as const).filter(k => c[k] == null)\n  if (missing.length > 0) {\n    throw new Error(`minio storage config missing: ${missing.join(', ')}`)\n  }\n}\nvalidateMinioConfig(minioEntry)","typeGuard":"function isMinioConfigReady (c: Partial<MinioConfig>): c is MinioConfig {\n  return c.endpoint != null && c.accessKey != null && c.secretKey != null\n}","tryCatchPattern":"try {\n  const adapter = createStorageFromConfig(cfg)\n} catch (err) {\n  if ((err as Error).message.includes('endpoint/accessKey/secretKey')) {\n    console.error('Incomplete minio config in STORAGE_CONFIG:', cfg.name)\n    process.exit(1)\n  }\n  throw err\n}","preventionTips":["Verify credential env vars are exported in the actual runtime container","Use docker/k8s secret injection rather than shell interpolation where possible","Smoke-test storage init at startup before accepting traffic","Keep param names exactly accessKey/secretKey in STORAGE_CONFIG URIs"],"tags":["configuration","minio","credentials","startup"],"backgroundTag":"missing-storage-credentials","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}