Skip to content

[BUG] Resource::Create() throws bad_variant_access if process.executable.name isn't a string #4535

Description

@brhenc

Describe your environment

Reproduced by source read + build on main at 11fa0db0 (also present in v1.28.0, the latest release -- not a regression). sdk/src/resource/resource.cc, Resource::Create.

Steps to reproduce

Resource Resource::Create(const ResourceAttributes &attributes, const std::string &schema_url)
{
  ...
  if (resource.attributes_.find(semconv::service::kServiceName) == resource.attributes_.end())
  {
    std::string default_service_name = "unknown_service";
    auto it_process_executable_name =
        resource.attributes_.find(semconv::process::kProcessExecutableName);
    if (it_process_executable_name != resource.attributes_.end())
    {
      default_service_name += ":" + nostd::get<std::string>(it_process_executable_name->second);
    }
    resource.attributes_[semconv::service::kServiceName] = default_service_name;
  }
  return resource;
}

it_process_executable_name->second is an AttributeValue (nostd::variant). nostd::get<std::string> throws if the variant doesn't currently hold a std::string. process.executable.name can end up holding a different alternative than std::string in more than one way: a custom ResourceDetector setting it directly, an environment/config-driven attribute source, or simply a caller passing it in attributes as const char*/string_view/an integer by mistake -- none of those are prevented by the ResourceAttributes type itself.

To trigger: call Resource::Create(attributes, schema_url) with attributes containing {"process.executable.name", <anything that isn't a std::string>} and no service.name already set.

What is the expected behavior?

If process.executable.name is present but not a string, Resource::Create should fall back to just "unknown_service" (or otherwise degrade gracefully) rather than crash.

What is the actual behavior?

nostd::get<std::string> throws nostd::bad_variant_access. Since Resource::Create (and its callers up through TracerProvider/LoggerProvider/MeterProvider construction) isn't inside any exception handling, this propagates out and terminates initialization -- often during process/provider startup or a reload, i.e. exactly when an application least wants an unhandled crash.

Additional context

Suggested fix -- use nostd::get_if instead of the throwing nostd::get, and simply skip the suffix if the attribute isn't a string:

     if (it_process_executable_name != resource.attributes_.end())
     {
-      default_service_name += ":" + nostd::get<std::string>(it_process_executable_name->second);
+      if (const auto *executable_name =
+              nostd::get_if<std::string>(&it_process_executable_name->second))
+      {
+        default_service_name += ":" + *executable_name;
+      }
     }

Compile-checked against a clean build of this file -- no warnings or errors. Happy to open a PR with this if useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedGood for taking. Extra help will be provided by maintainerstriage/acceptedIndicates an issue or PR is ready to be actively worked on.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions