SonarSource/sonarqube · error · IllegalStateException

Metadata has already been written

Error message

Metadata has already been written

What it means

DumpWriterImpl.write(ProjectDump.Metadata) writes the metadata protobuf file into the dump root, and each dump may contain exactly one metadata file. If write() is called a second time after metadata was already written, an IllegalStateException is thrown. This guards the dump-format invariant that metadata appears exactly once.

Source

Thrown at server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/steps/DumpWriterImpl.java:60

  private final ProjectExportDumpFS projectExportDumpFS;
  private final TempFolder tempFolder;
  private final File rootDir;

  private final AtomicBoolean metadataWritten = new AtomicBoolean(false);
  private final AtomicBoolean published = new AtomicBoolean(false);

  public DumpWriterImpl(ProjectDescriptor descriptor, ProjectExportDumpFS projectExportDumpFS, TempFolder tempFolder) {
    this.descriptor = descriptor;
    this.projectExportDumpFS = projectExportDumpFS;
    this.tempFolder = tempFolder;
    this.rootDir = tempFolder.newDir();
  }

  @Override
  public void write(ProjectDump.Metadata metadata) {
    checkNotPublished();
    if (metadataWritten.get()) {
      throw new IllegalStateException("Metadata has already been written");
    }
    File file = new File(rootDir, METADATA.filename());
    try (FileOutputStream output = FILES2.openOutputStream(file, false)) {
      PROTOBUF2.writeTo(metadata, output);
      metadataWritten.set(true);
    } catch (IOException e) {
      throw new IllegalStateException("Can not write to file " + file, e);
    }
  }

  @Override
  public <M extends Message> StreamWriter<M> newStreamWriter(DumpElement<M> elt) {
    checkNotPublished();
    File file = new File(rootDir, elt.filename());
    return StreamWriterImpl.create(file);
  }

  @Override

View on GitHub (pinned to 184c821202)

Solutions

  1. Locate the duplicate call to write(metadata) — only one step should write metadata per dump
  2. Ensure the metadata-writing step is executed exactly once in the step sequence
  3. If re-exporting, create a fresh DumpWriterImpl/rootDir instead of reusing a writer that already wrote metadata
Defensive patterns

Strategy: validation

Validate before calling

// ensure metadata step runs exactly once before executing steps
if (steps.stream().filter(MetadataWritingStep.class::isInstance).count() != 1) {
  throw new IllegalStateException("pipeline must contain exactly one metadata step");
}

Try / catch

try { writer.write(metadata); } catch (IllegalStateException e) { logger.error("Metadata double-write; pipeline misconfigured", e); }

Prevention

When it happens

Trigger: Calling dumpWriter.write(metadata) twice in one export session — e.g. a step executed twice, or two steps both writing metadata.

Common situations: Custom export pipeline steps accidentally including a metadata-writing step more than once; re-running a failed pipeline against a DumpWriter instance that already had metadata written.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/e91b733bb922ae15. Report an issue: GitHub.