{"record":{"id":"ce694ad07e833e3b","repo":"t8y2/dbx","slug":"failed-to-read-composite-fields-w","errorCode":null,"errorMessage":"failed to read composite fields: %w","messagePattern":"failed to read composite fields: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/kingbase-go/kingbase_metadata.go","lineNumber":818,"sourceCode":"\tindex := 0\n\tfor rows.Next() {\n\t\tvar label string\n\t\tvar sortOrder float64\n\t\tif err := rows.Scan(&label, &sortOrder); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// enumsortorder is float4; ALTER TYPE ... ADD VALUE BEFORE/AFTER can\n\t\t// yield fractional values. Use the ORDER BY position for a unique key.\n\t\tindex++\n\t\tmembers = append(members, customTypeMember{Ordinal: int32(index), EnumValue: &label})\n\t}\n\treturn members, rows.Err()\n}\n\nfunc (s *server) customTypeCompositeMembers(sqlTemplate string, typrelid int64) ([]customTypeMember, error) {\n\trows, err := s.metadataQuery(fmt.Sprintf(sqlTemplate, typrelid, typrelid))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read composite fields: %w\", err)\n\t}\n\tdefer rows.Close()\n\tvar members []customTypeMember\n\tfor rows.Next() {\n\t\tvar member customTypeMember\n\t\tvar hasDefault bool\n\t\tvar comment sql.NullString\n\t\tif err := rows.Scan(&member.Name, &member.DataType, &member.Ordinal, &member.Nullable, &hasDefault, &member.Default, &comment); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif !hasDefault {\n\t\t\tmember.Default = nil\n\t\t}\n\t\tmember.Comment = nullStringPtr(comment)\n\t\tmembers = append(members, member)\n\t}\n\treturn members, rows.Err()\n}","sourceCodeStart":800,"sourceCodeEnd":836,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/kingbase-go/kingbase_metadata.go#L800-L836","documentation":"After getTypeDetails classifies a type as composite (typtype 'c'), it runs customTypeCompositeMembers, which executes the composite-fields catalog SQL (querying attribute columns of the type's underlying relation via typrelid) through metadataQuery. If that query fails, the error is wrapped as 'failed to read composite fields', meaning the field list of the composite type cannot be built.","triggerScenarios":"Calling the type details API on a composite type whose field catalog query (join of pg_attribute/sys_attribute with pg_class/sys_class on typrelid) fails — the typrelid template is interpolated twice, so a malformed template or a catalog-access failure surfaces here.","commonSituations":"Role lacking SELECT on attribute/class catalogs; dropped relation behind a composite type leaving stale typrelid; Kingbase mode mismatch (sys_catalog vs pg_catalog) producing invalid SQL; transient DB errors.","solutions":["Inspect the wrapped inner error (%w) for the actual SQL failure","Grant the connecting role SELECT on pg_attribute/sys_attribute, pg_class/sys_class, and pg_type/sys_type","Ensure the driver's catalog-mode setting matches the server (postgresCatalog flag)","Recreate the composite type if its underlying relation row is missing/stale in the catalog"],"exampleFix":"// before\nrows, err := s.metadataQuery(fmt.Sprintf(sqlTemplate, typrelid, typrelid))\n// after — surface typrelid for diagnosis\nif err != nil { return nil, fmt.Errorf(\"failed to read composite fields (typrelid=%d): %w\", typrelid, err) }","handlingStrategy":"try-catch","validationCode":"// ensure the role can read attribute/class catalogs and that the type's relation exists\nif !roleCanSelect(\"pg_attribute\", \"pg_class\") && !roleCanSelect(\"sys_attribute\", \"sys_class\") { grantCompositeCatalogAccess() }\nif !typeRelationExists(typrelid) { recreateCompositeType(name) }","typeGuard":"func isCompositeDetails(details *customTypeDetails) bool {\n  return details != nil && details.Kind == \"composite\"\n} // only composites go through the field-listing path","tryCatchPattern":"details, err := server.GetTypeDetails(schema, name)\nif err != nil && strings.Contains(err.Error(), \"failed to read composite fields\") {\n  if isTransient(err) { return retryWithBackoff() }\n  return fmt.Errorf(\"composite fields unreadable for %s.%s: %w\", schema, name, err)\n}","preventionTips":["Grant SELECT on attribute/class catalogs to the introspection role","Recreate composite types whose backing relation rows are stale or dropped","Keep driver catalog-mode configuration aligned with the actual server mode"],"tags":["metadata","composite-type","catalog-query","kingbase"],"backgroundTag":"composite-catalog-query-failed","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}