{"record":{"id":"c9f60de9234bce83","repo":"apache/beam","slug":"duplicate-column-names-found-duplicates-postgres","errorCode":null,"errorMessage":"Duplicate column names found: {duplicates}","messagePattern":"Duplicate column names found: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/rag/ingestion/postgres.py","lineNumber":58,"sourceCode":"class _PostgresQueryBuilder:\n  def __init__(\n      self,\n      table_name: str,\n      *,\n      column_specs: list[ColumnSpec],\n      conflict_resolution: Optional[ConflictResolution] = None):\n    \"\"\"Builds SQL queries for writing EmbeddableItems to Postgres.\n    \"\"\"\n    self.table_name = table_name\n\n    self.column_specs = column_specs\n    self.conflict_resolution = conflict_resolution\n\n    # Validate no duplicate column names\n    names = [col.column_name for col in self.column_specs]\n    duplicates = set(name for name in names if names.count(name) > 1)\n    if duplicates:\n      raise ValueError(f\"Duplicate column names found: {duplicates}\")\n\n    # Create NamedTuple type\n    fields = [(col.column_name, col.python_type) for col in self.column_specs]\n    type_name = f\"VectorRecord_{table_name}\"\n    self.record_type = NamedTuple(type_name, fields)  # type: ignore\n\n    # Register coder\n    registry.register_coder(self.record_type, RowCoder)\n\n    # Set default update fields to all non-conflict fields if update fields are\n    # not specified\n    if self.conflict_resolution:\n      self.conflict_resolution.maybe_set_default_update_fields(\n          [col.column_name for col in self.column_specs if col.column_name])\n\n  def build_insert(self) -> str:\n    \"\"\"Build INSERT query with proper type casting.\"\"\"\n    # Get column names and placeholders","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/rag/ingestion/postgres.py#L40-L76","documentation":"PostgresVectorWriterConfig.__init__ validates that no two ColumnSpec entries share a column_name before generating the NamedTuple record type and SQL insert. Duplicate names would make the generated record type and INSERT ambiguous, so it fails fast.","triggerScenarios":"Passing column_specs with repeated column_name values to PostgresVectorWriterConfig — e.g. two add_vector/add_metadata calls with the same column, or merged spec lists containing the same column twice.","commonSituations":"Programmatic spec generation loops reusing a name; both a dense and sparse spec accidentally named 'embedding'; config merging that concatenates specs without de-duplication.","solutions":["Give each ColumnSpec a unique column_name matching distinct Postgres columns.","De-duplicate the specs list before constructing the writer config.","Split genuinely different data into separate table columns rather than reusing a name."],"exampleFix":"// before\nconfig.add_vector(\"embedding\").add_vector(\"embedding\")\n// after\nconfig.add_vector(\"embedding\").add_sparse_vector(\"sparse_embedding\")","handlingStrategy":"validation","validationCode":"names = [c.column_name for c in specs]\nassert len(names) == len(set(names)), f\"duplicates: {set(n for n in names if names.count(n) > 1)}\"","typeGuard":"def has_unique_columns(specs) -> bool:\n    names = [s.column_name for s in specs]\n    return len(names) == len(set(names))","tryCatchPattern":"try:\n    cfg = PostgresVectorWriterConfig(..., column_specs=specs)\nexcept ValueError as e:\n    if \"Duplicate column names\" in str(e):\n        seen = set(); specs = [s for s in specs if not (s.column_name in seen or seen.add(s.column_name))]\n        cfg = PostgresVectorWriterConfig(..., column_specs=specs)\n    else:\n        raise","preventionTips":["Keep a single ordered list of column definitions as source of truth","Name dense and sparse vector columns distinctly","Add a unit test constructing the config with production specs"],"tags":["python","postgres","rag","schema-validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}