{"record":{"id":"5ce0a87572533dfe","repo":"grpc/grpc-java","slug":"metric-with-name-name-already-exists","errorCode":null,"errorMessage":"Metric with name ${name} already exists","messagePattern":"Metric with name (.+?) already exists","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/grpc/MetricInstrumentRegistry.java","lineNumber":92,"sourceCode":"   * @param description a description of the metric\n   * @param unit the unit of measurement for the metric\n   * @param requiredLabelKeys a list of required label keys\n   * @param optionalLabelKeys a list of optional label keys\n   * @param enableByDefault whether the metric should be enabled by default\n   * @return the newly created DoubleCounterMetricInstrument\n   * @throws IllegalStateException if a metric with the same name already exists\n   */\n  public DoubleCounterMetricInstrument registerDoubleCounter(String name,\n      String description, String unit, List<String> requiredLabelKeys,\n      List<String> optionalLabelKeys, boolean enableByDefault) {\n    checkArgument(!Strings.isNullOrEmpty(name), \"missing metric name\");\n    checkNotNull(description, \"description\");\n    checkNotNull(unit, \"unit\");\n    checkNotNull(requiredLabelKeys, \"requiredLabelKeys\");\n    checkNotNull(optionalLabelKeys, \"optionalLabelKeys\");\n    synchronized (lock) {\n      if (registeredMetricNames.contains(name)) {\n        throw new IllegalStateException(\"Metric with name \" + name + \" already exists\");\n      }\n      int index = nextAvailableMetricIndex;\n      if (index + 1 == metricInstruments.length) {\n        resizeMetricInstruments();\n      }\n      // TODO(dnvindhya): add limit for number of optional labels allowed\n      DoubleCounterMetricInstrument instrument = new DoubleCounterMetricInstrument(\n          index, name, description, unit, requiredLabelKeys, optionalLabelKeys,\n          enableByDefault);\n      metricInstruments[index] = instrument;\n      registeredMetricNames.add(name);\n      nextAvailableMetricIndex += 1;\n      return instrument;\n    }\n  }\n\n  /**\n   * Registers a new Long Counter metric instrument.","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/api/src/main/java/io/grpc/MetricInstrumentRegistry.java#L74-L110","documentation":"MetricInstrumentRegistry.registerDoubleCounter registers a double counter metric instrument by unique name in a process-wide registry. Registering the same name twice throws IllegalStateException('Metric with name X already exists') to prevent conflicting definitions (labels/units) for one metric name.","triggerScenarios":"Calling registerDoubleCounter twice with the same metric name — typically during repeated SDK/library initialization, multiple registry instances sharing names, or classloader re-initialization within one JVM.","commonSituations":"Calling grpc initialization code twice (e.g. both app code and a framework plugin init metrics); hot redeploys in an app server that does not release the old registry; two versions of a library both registering the same metric name.","solutions":["Guard registration so it runs once per JVM (static init flag, singleton init)","Check name existence before registering, or dedupe metric names across libraries","In app servers, ensure the registry lifecycle is tied to the webapp classloader","Rename the metric if a genuine collision with another library exists"],"exampleFix":"// before\nregistry.registerDoubleCounter(\"rpc.duration\", desc, unit, labels, optionalLabels);\n// after\nif (!registered) {\n  registry.registerDoubleCounter(\"rpc.duration\", desc, unit, labels, optionalLabels);\n  registered = true;\n}","handlingStrategy":"try-catch","validationCode":"// no public pre-check API in older versions; guard at call site\nif (alreadyRegistered(\"rpc.duration\")) return; // track your own registration set","typeGuard":null,"tryCatchPattern":"try {\n  registry.registerDoubleCounter(name, desc, unit, labelKeys, optionalLabelKeys);\n} catch (IllegalStateException e) {\n  // duplicate metric name: log and continue if definition is identical\n}","preventionTips":["Initialize metrics once per process via a singleton or static initializer","Deduplicate metric names across libraries you integrate","Tie metric registration to classloader/app lifecycle in containers and app servers","Keep grpc versions aligned so built-in instruments are registered exactly once"],"tags":["grpc","metrics","duplicate-registration","illegal-state"],"backgroundTag":"internal-invariant-violation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}