pinpoint-apm/pinpoint · error · OtlpMappingException
Resource attribute `pinpoint.agentId` is required to save OT
Error message
Resource attribute `pinpoint.agentId` is required to save OTLP metrics to Pinpoint
What it means
parseCommonTags requires the resource attribute `pinpoint.agentId` (in addition to `service.name`) so metrics can be attributed to a specific agent in Pinpoint. When it is missing or empty, OtlpMappingException is thrown. Note the guard has a copy-paste bug: it re-checks `serviceName` instead of `agentId`, so this error only fires when service.name was also empty (or never when only agentId is empty) — a null/empty agentId silently flows into builder.setAgentId.
Source
Thrown at otlpmetric/otlpmetric-collector/src/main/java/com/navercorp/pinpoint/otlp/collector/mapper/OtlpMetricMapper.java:91
private void map(OtlpMetricData.Builder builder, Metric metric, Map<String, String> commonTags) {
for (OtlpMetricDataMapper mapper : mappers) {
mapper.map(builder, metric, commonTags);
}
}
private Map<String, String> parseCommonTags(OtlpMetricData.Builder builder, Map<String, String> tags) {
Map<String, String> commonTags = new HashMap<>(tags);
String serviceName = commonTags.remove(OtlpResourceAttributes.KEY_SERVICE_NAME);
if (StringUtils.isEmpty(serviceName)) {
throw new OtlpMappingException("Resource attribute `service.name` is required to save OTLP metrics to Pinpoint.");
}
builder.setServiceName(serviceName);
String agentId = commonTags.remove(OtlpResourceAttributes.KEY_PINPOINT_AGENTID);
if (StringUtils.isEmpty(serviceName)) {
throw new OtlpMappingException("Resource attribute `pinpoint.agentId` is required to save OTLP metrics to Pinpoint");
}
builder.setAgentId(agentId);
String version = commonTags.remove(OtlpResourceAttributes.KEY_PINPOINT_METRIC_VERSION);
if (StringUtils.isEmpty(version) == false) {
builder.setVersion(version);
}
return commonTags;
}
}
View on GitHub (pinned to 744c3d3075)
Solutions
- Add the `pinpoint.agentId` resource attribute on the exporter (Resource.builder().put("pinpoint.agentId", agentId)).
- Fix the mapper bug so the guard checks the right variable: `if (StringUtils.isEmpty(agentId)) throw ...` (see exampleFix).
- If routing through a Collector, use a `resource` processor to inject pinpoint.agentId before export.
- Verify the exact attribute key matches OtlpResourceAttributes.KEY_PINPOINT_AGENTID for your Pinpoint version (naming drift across versions).
Example fix
// before (OtlpMetricMapper.java)
String agentId = commonTags.remove(OtlpResourceAttributes.KEY_PINPOINT_AGENTID);
if (StringUtils.isEmpty(serviceName)) {
throw new OtlpMappingException("Resource attribute `pinpoint.agentId` is required to save OTLP metrics to Pinpoint");
}
// after
String agentId = commonTags.remove(OtlpResourceAttributes.KEY_PINPOINT_AGENTID);
if (StringUtils.isEmpty(agentId)) {
throw new OtlpMappingException("Resource attribute `pinpoint.agentId` is required to save OTLP metrics to Pinpoint");
} Defensive patterns
Strategy: validation
Validate before calling
Resource res = Resource.getDefault();
String agentId = res.getAttributes().get(AttributeKey.stringKey("pinpoint.agentId"));
String serviceName = res.getAttributes().get(AttributeKey.stringKey("service.name"));
if (isBlank(serviceName) || isBlank(agentId)) {
throw new IllegalStateException("Pinpoint OTLP export requires `service.name` and `pinpoint.agentId` resource attributes");
} Type guard
boolean hasAgentId(io.opentelemetry.api.common.Attributes attrs) {
String v = attrs.get(AttributeKey.stringKey("pinpoint.agentId"));
return v != null && !v.isEmpty();
} Try / catch
try {
exporter.export(metrics);
} catch (OtlpMappingException e) {
log.error("Missing Pinpoint resource attribute: {}", e.getMessage());
} Prevention
- Set pinpoint.agentId alongside service.name in the Resource on every exporter.
- Keep the attribute key in a shared constant and verify it matches OtlpResourceAttributes.KEY_PINPOINT_AGENTID for your Pinpoint version.
- When upgrading Pinpoint, diff the OtlpResourceAttributes key set and update exporters.
- Review mapper guards for copy-paste mistakes (this one checked serviceName instead of agentId).
When it happens
Trigger: An OTLP metrics payload whose Resource lacks the `pinpoint.agentId` attribute (OtlpResourceAttributes.KEY_PINPOINT_AGENTID) reaches parseCommonTags and service.name is also empty; or the attribute exists but is blank while the faulty serviceName check still evaluates true.
Common situations: 1) Emitting via a stock OpenTelemetry SDK which knows nothing about Pinpoint's custom `pinpoint.agentId` attribute. 2) A Collector `resource` processor that strips non-standard attributes. 3) Version change in the Pinpoint OTLP contract where the attribute key was renamed.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Resource attribute `service.name` is required to save OTLP m
- value
- N:N relationship between fields and tags is not allowed.
- Either tagGroupList or fieldNameList must have a size of exa
- invalid traceId: ${error}
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/57f03a59b448f25d.
Report an issue: GitHub.