{"record":{"id":"90e55afe4ca8fae0","repo":"JuliusBrussee/caveman","slug":"cavemanexporterconfig-protocol-protocol-is-not","errorCode":null,"errorMessage":"cavemanExporterConfig: protocol ${protocol} is not accepted by ${baseUrl}/otlp/v1/traces; the Caveman OTLP endpoint decodes protobuf-JSON only. Use 'http/json'.","messagePattern":"cavemanExporterConfig: protocol (.+?) is not accepted by (.+?)/otlp/v1/traces; the Caveman OTLP endpoint decodes protobuf-JSON only\\. Use 'http/json'\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mastra/src/index.ts","lineNumber":93,"sourceCode":" * Builds the OTLP settings a Mastra application passes to its telemetry config.\n *\n * The endpoint is Caveman's OTLP route (`POST {baseUrl}/otlp/v1/traces`). That\n * handler decodes protobuf-JSON, not binary protobuf, so `http/json` is the only\n * protocol it can accept — a protobuf or gRPC batch is rejected rather than\n * silently dropped here.\n *\n * Auth: the gateway reads `x-cave-api-key` first and falls back to\n * `authorization` (a `Bearer ` prefix is stripped before the key is parsed), so\n * both headers are emitted and either one alone would authenticate.\n */\nexport function cavemanExporterConfig(options: CavemanExporterOptions): CavemanExporterConfig {\n  const baseUrl = requireBaseUrl(options.baseUrl, \"cavemanExporterConfig: baseUrl\");\n  const apiKey = requireNonEmpty(options.apiKey, \"cavemanExporterConfig: apiKey\");\n  const projectId = requireNonEmpty(options.projectId, \"cavemanExporterConfig: projectId\");\n  const environment = requireNonEmpty(options.environment, \"cavemanExporterConfig: environment\");\n  const protocol = options.protocol ?? \"http/json\";\n  if (protocol !== \"http/json\") {\n    throw new Error(\n      `cavemanExporterConfig: protocol ${protocol} is not accepted by ${baseUrl}/otlp/v1/traces; ` +\n        \"the Caveman OTLP endpoint decodes protobuf-JSON only. Use 'http/json'.\",\n    );\n  }\n\n  const endpoint = `${baseUrl}/otlp/v1/traces`;\n  const headers: Record<string, string> = {\n    \"x-cave-api-key\": apiKey,\n    authorization: `Bearer ${apiKey}`,\n  };\n  if (options.agentId) headers[\"x-cave-agent\"] = options.agentId;\n  Object.assign(headers, options.headers ?? {});\n\n  // §23.3 of docs/self_learning_implementation_spec.md — the required metadata block.\n  const resourceAttributes: Record<string, string> = {\n    \"caveman.project.id\": projectId,\n    \"caveman.environment\": environment,\n  };","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/packages/mastra/src/index.ts#L75-L111","documentation":"cavemanExporterConfig builds an OTLP trace exporter pointed at the Caveman gateway, whose /otlp/v1/traces endpoint decodes protobuf-JSON only. The protocol option exists mainly to catch configs copied from standard OpenTelemetry setups: anything other than 'http/json' (the default) is rejected up front, instead of failing later with opaque 4xx responses from the gateway.","triggerScenarios":"cavemanExporterConfig({ baseUrl, apiKey, projectId, environment, protocol: 'grpc' }) or protocol: 'http/protobuf' — the values standard OTLP Node SDKs and collector configs use.","commonSituations":"Porting an existing OpenTelemetry config where http/protobuf or grpc is the norm; a version upgrade that added protocol validation to previously-silent misconfiguration; copy-paste from generic OTLP exporter docs.","solutions":["Omit the protocol option entirely — it defaults to 'http/json'","Or set protocol: 'http/json' explicitly","Keep transport concerns in options.headers (custom auth headers), not protocol"],"exampleFix":"// before\nconst cfg = cavemanExporterConfig({ baseUrl, apiKey, projectId, environment, protocol: 'http/protobuf' });\n\n// after\nconst cfg = cavemanExporterConfig({ baseUrl, apiKey, projectId, environment }); // defaults to 'http/json'","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"type CavemanProtocol = 'http/json';\n\nfunction isSupportedProtocol(value: unknown): value is CavemanProtocol {\n  return value === undefined || value === 'http/json';\n}","tryCatchPattern":null,"preventionTips":["Omit the protocol option — 'http/json' is the only supported and default value","When porting OpenTelemetry configs, strip protocol/transport fields before reuse","Type exporter options narrowly so unsupported protocol literals fail at compile time"],"tags":["opentelemetry","otlp","tracing","config","exporter","mastra"],"backgroundTag":"otlp-protocol-mismatch","analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}