{"record":{"id":"e91b733bb922ae15","repo":"SonarSource/sonarqube","slug":"metadata-has-already-been-written","errorCode":null,"errorMessage":"Metadata has already been written","messagePattern":"Metadata has already been written","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/steps/DumpWriterImpl.java","lineNumber":60,"sourceCode":"  private final ProjectExportDumpFS projectExportDumpFS;\n  private final TempFolder tempFolder;\n  private final File rootDir;\n\n  private final AtomicBoolean metadataWritten = new AtomicBoolean(false);\n  private final AtomicBoolean published = new AtomicBoolean(false);\n\n  public DumpWriterImpl(ProjectDescriptor descriptor, ProjectExportDumpFS projectExportDumpFS, TempFolder tempFolder) {\n    this.descriptor = descriptor;\n    this.projectExportDumpFS = projectExportDumpFS;\n    this.tempFolder = tempFolder;\n    this.rootDir = tempFolder.newDir();\n  }\n\n  @Override\n  public void write(ProjectDump.Metadata metadata) {\n    checkNotPublished();\n    if (metadataWritten.get()) {\n      throw new IllegalStateException(\"Metadata has already been written\");\n    }\n    File file = new File(rootDir, METADATA.filename());\n    try (FileOutputStream output = FILES2.openOutputStream(file, false)) {\n      PROTOBUF2.writeTo(metadata, output);\n      metadataWritten.set(true);\n    } catch (IOException e) {\n      throw new IllegalStateException(\"Can not write to file \" + file, e);\n    }\n  }\n\n  @Override\n  public <M extends Message> StreamWriter<M> newStreamWriter(DumpElement<M> elt) {\n    checkNotPublished();\n    File file = new File(rootDir, elt.filename());\n    return StreamWriterImpl.create(file);\n  }\n\n  @Override","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/steps/DumpWriterImpl.java#L42-L78","documentation":"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.","triggerScenarios":"Calling dumpWriter.write(metadata) twice in one export session — e.g. a step executed twice, or two steps both writing metadata.","commonSituations":"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.","solutions":["Locate the duplicate call to write(metadata) — only one step should write metadata per dump","Ensure the metadata-writing step is executed exactly once in the step sequence","If re-exporting, create a fresh DumpWriterImpl/rootDir instead of reusing a writer that already wrote metadata"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure metadata step runs exactly once before executing steps\nif (steps.stream().filter(MetadataWritingStep.class::isInstance).count() != 1) {\n  throw new IllegalStateException(\"pipeline must contain exactly one metadata step\");\n}","typeGuard":null,"tryCatchPattern":"try { writer.write(metadata); } catch (IllegalStateException e) { logger.error(\"Metadata double-write; pipeline misconfigured\", e); }","preventionTips":["Register the metadata-writing step exactly once in the export step sequence","Never reuse a DumpWriter instance across export runs","Track pipeline execution order in tests"],"tags":["sonarqube","project-export","state","duplicate-write"],"backgroundTag":"invalid-state-transition","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}