Skip to content

Bug: Parca server panics when receiving OTLP Profile signal #5897

@AntoxaBarin

Description

@AntoxaBarin

Panic stacktrace:

*Parca logo*
level=info name=parca ts=2025-08-20T07:39:32.111257566Z caller=factory.go:53 msg="loading bucket configuration"
level=info name=parca ts=2025-08-20T07:39:32.114592063Z caller=badgerlogger.go:36 msg="Set nextTxnTs to 0"
level=info name=parca ts=2025-08-20T07:39:32.11654715Z caller=server.go:90 msg="starting server" addr=:7070
panic: runtime error: index out of range [2] with length 0

goroutine 245 [running]:
github.com/parca-dev/parca/pkg/normalizer.(*labelNames).addOtelAttributesFromTable(0xc00069c980, {0x0, 0x0, 0x0}, {0xc000d398b0, 0x3, 0x3})
        /home/parca/pkg/normalizer/otel.go:88 +0x13c
github.com/parca-dev/parca/pkg/normalizer.getAllLabelNames(0xc00098fa40)
        /home/parca/pkg/normalizer/otel.go:147 +0x3d9
github.com/parca-dev/parca/pkg/normalizer.OtlpRequestToArrowRecord({0x8792850, 0xc0065bf560}, 0xc00098fa40, 0xc0006c70e0, {0x87706a0, 0xb63a260})
        /home/parca/pkg/normalizer/otel.go:51 +0x1b7
github.com/parca-dev/parca/pkg/profilestore.(*ProfileColumnStore).Export(0xc000320540, {0x8792850, 0xc0065bf560}, 0xc00098fa40)
...

From OTLP proto specification (commit 3ec4649f):

message Sample {
  // locations_start_index along with locations_length refers to to a slice of locations in Profile.location_indices.
  int32 locations_start_index = 1;
  // locations_length along with locations_start_index refers to a slice of locations in Profile.location_indices.
  // Supersedes location_index.
  int32 locations_length = 2;
  // The type and unit of each value is defined by Profile.sample_type.
  repeated int64 values = 3;
  // References to attributes in ProfilesDictionary.attribute_table. [optional]
  repeated int32 attribute_indices = 4;

  // Reference to link in ProfilesDictionary.link_table. [optional]
  // It can be unset / set to 0 if no link exists, as link_table[0] is always a 'null' default value.
  int32 link_index = 5;

  // Timestamps associated with Sample represented in nanoseconds. These
  // timestamps should fall within the Profile's time range.
  repeated fixed64 timestamps_unix_nano = 6;
}

pkg/normalizer/otel.go:136-156:

func getAllLabelNames(req *otelgrpcprofilingpb.ExportProfilesServiceRequest) []string {
	allLabelNames := newLabelNames()

	for _, rp := range req.ResourceProfiles {
		allLabelNames.addOtelAttributes(rp.Resource.Attributes)

		for _, sp := range rp.ScopeProfiles {
			allLabelNames.addOtelAttributes(sp.Scope.Attributes)

			for _, p := range sp.Profiles {
				allLabelNames.addOtelAttributesFromTable(sp.Scope.Attributes, p.AttributeIndices)

				for _, sample := range p.Sample {
					allLabelNames.addOtelAttributesFromTable(sp.Scope.Attributes, sample.AttributeIndices)
                                                              ^^^^^^^^^^^^^^^^                                                                                                                          
				}
			}
		}
	}

	return allLabelNames.sorted()
}

Why do we lookup Sample's attribute in InstrumentationScope.attributes? Shouldn't we use ProfilesDictionary.attribute_table instead?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions