n8n-io/n8n · warning · Error
LangSmithTelemetry creates its own tracer — do not use .otlp
Error message
LangSmithTelemetry creates its own tracer — do not use .otlpEndpoint().
What it means
Thrown by the HTTP Request validator when a sensitive header (Authorization, X-API-Key, X-Auth-Token, X-Access-Token, API-Key, APIKey — matched case-insensitively) is set to a literal value rather than an n8n expression or credential. The validator wants secrets to live in the credential system so they never get serialized into the workflow JSON. A hardcoded secret here is a leak risk and also blocks proper credential reuse.
Source
Thrown at packages/@n8n/agents/src/integrations/langsmith.ts:372
*
* const agent = new Agent('assistant')
* .model('anthropic/claude-sonnet-4-5')
* .telemetry(telemetry)
* .instructions('...');
* ```
*/
export class LangSmithTelemetry extends Telemetry {
private langsmithConfig?: LangSmithTelemetryConfig;
constructor(config?: LangSmithTelemetryConfig) {
super();
this.langsmithConfig = config;
}
/** @override Build telemetry config, creating the LangSmith tracer. */
override async build(): Promise<BuiltTelemetry> {
if (this.otlpEndpointValue !== undefined) {
throw new Error('LangSmithTelemetry creates its own tracer — do not use .otlpEndpoint().');
}
// Clear any tracer from a previous build() so the parent's
// .tracer()/.otlpEndpoint() mutual-exclusion check passes cleanly.
this.tracerValue = undefined;
// The LangSmith exporter silently drops all spans unless this is set.
// Auto-enable it so users don't have to remember a magic env var.
process.env.LANGCHAIN_TRACING_V2 ??= 'true';
const { tracer, provider } = await createLangSmithTracer(
this.langsmithConfig,
this.resolvedKey,
);
this.tracerValue = tracer;
// Call parent build() which handles integrations, redaction, etc.
const built = await super.build();View on GitHub (pinned to 5ac6606e81)
Solutions
- Move the secret into a credential: create an httpHeaderAuth or httpBearerAuth credential and reference it from the node instead of the header parameter.
- If the provider uses 'Authorization: Bearer <token>', create a new credential with genericAuthType='httpTemplatedCustomAuth' and template {"headers":{"Authorization":"Bearer {{api_key}}"}}.
- If you must keep the header inline for a throwaway test, wrap the value in an expression so it is not treated as a hardcoded literal (e.g. value: expr('<token>')) — but prefer a credential for anything persisted.
- Reuse an existing httpHeaderAuth/httpBearerAuth credential id instead of creating a new one.
Example fix
// before
httpRequest({
name: 'Get Data',
headerParameters: { parameters: [{ name: 'Authorization', value: 'Bearer abc123secret' }] },
});
// after — reuse a header auth credential
httpRequest({
name: 'Get Data',
authentication: 'genericCredentialType',
genericAuthType: 'httpHeaderAuth',
credentials: { httpHeaderAuth: { id: 'EXISTING_CRED_ID' } },
}); Defensive patterns
Strategy: validation
Validate before calling
import { isSensitiveHeader, containsExpression } from './validation-helpers';
function findHardcodedSensitiveHeaders(headerParameters: { parameters?: Array<{ name?: string; value?: unknown }> } | undefined): string[] {
const offenders: string[] = [];
for (const h of headerParameters?.parameters ?? []) {
const valueStr = typeof h.value === 'string' ? h.value : JSON.stringify(h.value);
if (h.name && isSensitiveHeader(h.name) && h.value && !containsExpression(valueStr)) {
offenders.push(h.name);
}
}
return offenders;
}
// before building the node:
const bad = findHardcodedSensitiveHeaders(params.headerParameters);
if (bad.length) throw new Error(`Move these headers into a credential: ${bad.join(', ')}`); Type guard
function isExpressionValue(value: unknown): boolean {
return typeof value === 'string' && (value.startsWith('=') || value.includes('={{'));
} Prevention
- Never type a real secret into headerParameters; always reference a credential.
- Run validate_workflow in CI and fail on any HARDCODED_CREDENTIALS issue.
- Keep a small allowlist of test-only header values that are clearly fake.
When it happens
Trigger: A node of type n8n-nodes-base.httpRequest whose parameters.headerParameters.parameters[] contains an entry where header.name lowercases to one of the sensitive set, header.value is truthy, and the value string neither starts with '=' nor contains '={{'. The exact gate is isSensitiveHeader(name) && value && !containsExpression(value).
Common situations: An LLM/AI builder pastes a curl-derived 'Authorization: Bearer <real token>' straight into headerParameters; copying vendor docs that show the API key inline; testing with a real key and forgetting to swap it for a credential reference.
Related errors
- No suspended run found for runId: ${this.runId}
- Invalid resume payload: ${parseResult.error}
- Episodic memory requires a resolved embedding model before r
- Invalid credentials for provider "${provider}": ${issues}
- No tool call found for toolCallId: ${options.toolCallId}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/530e93a9d7fcaee1.
Report an issue: GitHub.