{"record":{"id":"20e596654c01d2a5","repo":"hcengineering/platform","slug":"endpoint-value-is-not-specified","errorCode":null,"errorMessage":"Endpoint value is not specified","messagePattern":"Endpoint value is not specified","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"foundations/server/packages/server-storage/src/starter.ts","lineNumber":98,"sourceCode":"export 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')\n    }\n    adapter = new HulylakeService(c)\n  } else {\n    throw new Error('Unsupported storage kind:' + kind)\n  }\n\n  if (config.readonly === 'true') {\n    adapter = new ReadonlyStorageAdapter(adapter)\n  }\n\n  return adapter\n}","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/server-storage/src/starter.ts#L80-L116","documentation":"createStorageFromConfig in server-storage builds a DatalakeService when the config kind is DATALAKE_CONFIG_KIND. Before constructing the adapter it checks that the DatalakeConfig has an endpoint; if `c.endpoint == null` (undefined or null) it throws this error, because a datalake storage adapter cannot function without a service endpoint URL.","triggerScenarios":"Calling createStorageFromConfig(config) where config.kind === DATALAKE_CONFIG_KIND but config.endpoint is undefined or null — e.g. a workspace/storage config loaded from DB or env that omitted the endpoint field.","commonSituations":"Hand-written storage config JSON missing 'endpoint'; env-driven config where the endpoint variable was never set; config migrated from another storage kind that has no endpoint field.","solutions":["Add a valid endpoint URL to the DatalakeConfig object passed to createStorageFromConfig","Check where the config is loaded (DB workspace config, env vars) and ensure the endpoint field is populated","Validate the config before calling createStorageFromConfig"],"exampleFix":"// before\nconst config = { kind: 'datalake', readOnly: 'false' }\ncreateStorageFromConfig(config)\n// after\nconst config = { kind: 'datalake', endpoint: 'https://datalake.example.com', readOnly: 'false' }\nif (config.endpoint == null) throw new Error('datalake endpoint missing')\ncreateStorageFromConfig(config)","handlingStrategy":"validation","validationCode":"function assertDatalakeConfig(cfg) {\n  if (cfg.kind === 'datalake' && (cfg.endpoint == null || cfg.endpoint === '')) {\n    throw new Error(`datalake config requires endpoint, got: ${cfg.endpoint}`)\n  }\n}","typeGuard":"function isDatalakeConfig(c) {\n  return typeof c === 'object' && c !== null && c.kind === 'datalake' &&\n    typeof c.endpoint === 'string' && c.endpoint.length > 0\n}","tryCatchPattern":"try {\n  adapter = createStorageFromConfig(cfg)\n} catch (e) {\n  if (e.message === 'Endpoint value is not specified') {\n    throw new Error(`storage config for kind '${cfg.kind}' is missing endpoint`)\n  }\n  throw e\n}","preventionTips":["Validate storage configs at load time with a schema (zod/io-ts) before they reach createStorageFromConfig","Add a startup smoke test that constructs every configured storage adapter","Document required fields per storage kind next to the config template"],"tags":["storage","configuration","validation"],"backgroundTag":"missing-config-field","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}