OpenTelemetry Error Guide: missing 'service.name' resource — Fix 'unknown_service'
Fix a missing service.name resource in OpenTelemetry: set OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES so telemetry stops landing under 'unknown_service' and services are identifiable.
- #opentelemetry
- #observability
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
When an OpenTelemetry SDK exports telemetry without a service.name resource attribute, the SDK logs a warning and falls back to a default name. Backends then group all such telemetry under one meaningless service:
2026-07-09T12:04:18.771Z warn OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES are not set; resource is missing the required service.name attribute, defaulting to "unknown_service"
Per the OpenTelemetry resource semantic conventions, service.name is required. If it is absent, SDKs default it to unknown_service (often unknown_service:<process>), and every unnamed workload collapses into the same bucket in your backend.
Symptoms
- Traces, metrics, and logs appear under
unknown_service(orunknown_service:java, etc.). - Multiple distinct workloads are indistinguishable because they share the default name.
- Service maps and dependency graphs are broken or collapsed.
- SDK startup logs warn that
service.nameis missing. - Alerts and dashboards keyed on
service.namematch nothing or match everything.
Common Root Causes
- No
OTEL_SERVICE_NAMEset — the simplest and most common cause. service.namenot inOTEL_RESOURCE_ATTRIBUTES— resource attributes set but the key omitted.- Resource not passed to the provider — manual SDK setup that never attaches a
Resourcewithservice.name. - Env var not propagated — set in the shell but missing in the container/pod spec.
- Overwritten by a processor — a Collector
resourceprocessor deletes or blanks the attribute. - Auto-instrumentation without config — an agent attached but never given a service name.
Diagnostic Workflow
Set the service name the canonical way. OTEL_SERVICE_NAME takes precedence and is the least error-prone:
export OTEL_SERVICE_NAME="checkout-api"
# or, with more resource attributes at once:
export OTEL_RESOURCE_ATTRIBUTES="service.name=checkout-api,service.namespace=shop,service.version=1.4.2,deployment.environment=production"
In Kubernetes, inject these from the pod spec so every replica is labeled consistently:
env:
- name: OTEL_SERVICE_NAME
value: "checkout-api"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "service.namespace=shop,deployment.environment=production"
As a safety net, have the Collector enforce or backfill service.name for anything arriving unnamed, using the resource processor:
processors:
resource:
attributes:
- key: service.name
value: "unnamed-fallback"
action: insert # insert only if absent; does not overwrite
service:
pipelines:
traces:
receivers: [otlp]
processors: [resource, batch]
exporters: [otlp]
Verify what the SDK actually emitted by inspecting the resource with the debug exporter:
journalctl -u otelcol-contrib --since '10 min ago' | grep -iA5 'Resource attributes'
Example Root Cause Analysis
A Java service used the OpenTelemetry auto-instrumentation agent via -javaagent, but the deployment set no service name — neither OTEL_SERVICE_NAME nor a service.name entry in OTEL_RESOURCE_ATTRIBUTES. Every trace exported with service.name=unknown_service:java. Because three different Java apps in the namespace all lacked the setting, they merged into one unknown_service:java node, making the service map useless.
The fix set OTEL_SERVICE_NAME per Deployment (checkout-api, catalog-api, payments-api) directly in each pod spec, so each workload emitted a distinct, correct resource. To catch future omissions, the gateway Collector added a resource processor with action: insert on service.name (fallback unnamed-fallback) and an alert on any telemetry still carrying that fallback. The service map immediately split back into three correctly named services.
Prevention Best Practices
- Always set
OTEL_SERVICE_NAME(orservice.nameinOTEL_RESOURCE_ATTRIBUTES) for every workload. - Inject the value from the deployment manifest, not a baked-in default, so replicas stay consistent.
- Include richer resource attributes (
service.namespace,service.version,deployment.environment) for filtering. - Add a Collector
resourceprocessor withaction: insertas a fallback so nothing is truly anonymous. - Alert on any telemetry arriving as
unknown_serviceor the fallback name. - Never let a
resourceprocessor useaction: upsert/updateonservice.nameunless you intend to overwrite it.
Quick Command Reference
# Confirm the service name is set for the process
env | grep -E 'OTEL_SERVICE_NAME|OTEL_RESOURCE_ATTRIBUTES'
# In Kubernetes, check the injected env
kubectl set env deploy/checkout-api --list | grep OTEL
# Inspect the resource actually emitted
journalctl -u otelcol-contrib | grep -iA5 'Resource attributes'
# Find telemetry still landing under unknown_service (backend query varies)
journalctl -u otelcol-contrib | grep -i 'unknown_service'
Conclusion
A missing service.name is a small omission with an outsized effect: it collapses distinct workloads into unknown_service and breaks every view keyed on service identity. The fix is simple and durable — set OTEL_SERVICE_NAME from each deployment’s spec, enrich with namespace/version/environment, and add a Collector resource fallback plus an alert so nothing ships anonymous. With identity attached at the source, your traces, metrics, and service maps become meaningful again.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.