{"record":{"id":"9f5f88f6cf8355f3","repo":"SonarSource/sonarqube","slug":"no-column-has-been-defined","errorCode":null,"errorMessage":"No column has been defined","messagePattern":"No column has been defined","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/AddColumnsBuilder.java","lineNumber":53,"sourceCode":"public class AddColumnsBuilder {\n\n  private final Dialect dialect;\n  private final String tableName;\n  private List<ColumnDef> columnDefs = newArrayList();\n\n  public AddColumnsBuilder(Dialect dialect, String tableName) {\n    this.tableName = validateTableName(tableName);\n    this.dialect = dialect;\n  }\n\n  public AddColumnsBuilder addColumn(ColumnDef columnDef) {\n    columnDefs.add(columnDef);\n    return this;\n  }\n\n  public String build() {\n    if (columnDefs.isEmpty()) {\n      throw new IllegalStateException(\"No column has been defined\");\n    }\n\n    StringBuilder sql = new StringBuilder().append(\"ALTER TABLE \").append(tableName).append(\" \");\n    switch (dialect.getId()) {\n      case PostgreSql.ID:\n        addColumns(sql, \"ADD COLUMN \");\n        break;\n      case MsSql.ID:\n        sql.append(\"ADD \");\n        addColumns(sql, \"\");\n        break;\n      default:\n        sql.append(\"ADD (\");\n        addColumns(sql, \"\");\n        sql.append(\")\");\n    }\n    return sql.toString();\n  }","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/AddColumnsBuilder.java#L35-L71","documentation":"Thrown by AddColumnsBuilder.build() when ALTER TABLE SQL generation is requested but no column was registered. The builder produces 'ALTER TABLE ... ADD COLUMN ...' statements and requires at least one columnDef added via addColumn().","triggerScenarios":"Calling build() on an AddColumnsBuilder without ever calling addColumn(...), e.g. a migration that conditionally skips adding columns but still builds the statement.","commonSituations":"Custom migration code guarded by a schema check where all branches fail to add columns; copy-pasted migration that forgot the addColumn call; refactored migration where columnDefs list ended up empty.","solutions":["Add at least one addColumn(...) call before build().","If the column may already exist, skip creating/invoking the builder entirely instead of building it empty.","Guard build() with a check on the batch's column count."],"exampleFix":"// before\nAddColumnsBuilder add = new AddColumnsBuilder(dialect, \"issues\");\nString sql = add.build();\n// after\nAddColumnsBuilder add = new AddColumnsBuilder(dialect, \"issues\");\nadd.addColumn(newVarcharColumnDefBuilder().setColumnName(\"branch\").setLimit(255).build());\nString sql = add.build();","handlingStrategy":"validation","validationCode":"if (builderColumns.isEmpty()) { throw new IllegalArgumentException(\"AddColumnsBuilder requires at least one column\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call addColumn(...) immediately after constructing the builder","Wrap builder construction and build() together so emptiness is obvious","Skip the migration step entirely when there is nothing to add","Code-review custom migrations for unconditional build() calls"],"tags":["database","migration","sql-builder"],"backgroundTag":"empty-required-field","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}