{"record":{"id":"cfdb20dd1c76f724","repo":"apache/druid","slug":"empty-columns","errorCode":null,"errorMessage":"Empty columns","messagePattern":"Empty columns","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/data/input/impl/DelimitedValueReader.java","lineNumber":185,"sourceCode":"  public void processHeaderLine(byte[] line) throws IOException\n  {\n    if (!findColumnsFromHeader) {\n      throw new ISE(\"Don't call this if findColumnsFromHeader = false\");\n    }\n    setSignature(parser.parseLine(line));\n  }\n\n  /**\n   * Set {@link #inputRowDimensions} and {@link #inputRowSignature} based on a set of header columns. Must be called\n   * prior to {@link #parseInputRows(byte[])}.\n   *\n   * @param columns header columns\n   */\n  private void setSignature(final List<String> columns)\n  {\n    inputRowSignature = findOrCreateInputRowSignature(columns);\n    if (inputRowSignature.size() == 0) {\n      throw new ISE(\"Empty columns\");\n    }\n\n    inputRowDimensions = MapInputRowParser.findDimensions(\n        getInputRowSchema().getTimestampSpec(),\n        getInputRowSchema().getDimensionsSpec(),\n        ImmutableSet.copyOf(inputRowSignature.getColumnNames())\n    );\n  }\n}\n","sourceCodeStart":167,"sourceCodeEnd":195,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/data/input/impl/DelimitedValueReader.java#L167-L195","documentation":"Thrown by DelimitedValueReader.setSignature when the header line of a delimited (CSV/TSV) input yields zero columns, so no InputRowSignature can be built. The library cannot parse records without a column list, so it fails fast during input-format initialization.","triggerScenarios":"Using DelimitedValueReader/DelimitedInputFormat with findColumnsFromHeader=true on a file whose first line is blank or whose header parses to an empty column list (e.g. wrong delimiter so the whole header is one empty token, or an empty file).","commonSituations":"Pointing ingestion at an empty file or a file with only a BOM/blank first line; a delimiter mismatch (e.g. file is semicolon-delimited but configured as comma) making column parsing degenerate; header row absent but findColumnsFromHeader enabled.","solutions":["Set an explicit 'columns' list in the inputFormat so the header is not relied upon","Verify the 'delimiter' and 'listDelimiter' match the actual file format","Check that the input file is non-empty and actually contains a header line as its first row","Skip leading blank lines or re-export the file without a BOM/blank header"],"exampleFix":"// before\n\"inputFormat\": {\"type\": \"csv\", \"findColumnsFromHeader\": true} // file has no header\n// after\n\"inputFormat\": {\"type\": \"csv\", \"columns\": [\"ts\", \"user\", \"value\"]}","handlingStrategy":"validation","validationCode":"// Before ingestion, verify the header yields columns\nList<String> header = readFirstLine(file, delimiter);\nif (header == null || header.stream().allMatch(String::isBlank)) {\n    throw new IllegalArgumentException(\"Input file has no usable header; set explicit columns\");\n}","typeGuard":null,"tryCatchPattern":"try { reader.beginParsing(); } catch (IllegalStateException e) { if (e.getMessage().contains(\"Empty columns\")) { /* fall back to explicit columns */ } }","preventionTips":["Always ship an explicit 'columns' list for delimited formats in production specs","Validate delimiter/listDelimiter against a sample of the real file before submitting the task","Check files for BOMs and blank first lines in your upload pipeline"],"tags":["csv","input-format","configuration"],"backgroundTag":"empty-required-field","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}