{"record":{"id":"713d8a554ea14749","repo":"t8y2/dbx","slug":"custom-type-s-s-is-not-fully-defined-713d8a","errorCode":null,"errorMessage":"custom type %s.%s is not fully defined","messagePattern":"custom type (.+?)\\.(.+?) is not fully defined","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/vastbase-go/vastbase_metadata.go","lineNumber":635,"sourceCode":"\t\tif err := rows.Err(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read type %s.%s: %w\", schema, name, err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"custom type %s.%s does not exist\", schema, name)\n\t}\n\tvar oid, typbasetype, typrelid, typelem, typcollation int64\n\tvar typtype, typalign, typstorage string\n\tvar typisdefined, typnotnull, typbyval bool\n\tvar typdefaultbin, typdefault, inputFn, outputFn, receiveFn, sendFn, analyzeFn, comment, collname, relkind sql.NullString\n\tvar typlen sql.NullInt64\n\tvar typtypmod int64\n\tif err := rows.Scan(&oid, &typtype, &typisdefined, &typbasetype, &typnotnull, &typrelid, &typelem, &typcollation, &typdefaultbin, &typdefault, &typlen, &typbyval, &typalign, &typstorage, &typtypmod, &inputFn, &outputFn, &receiveFn, &sendFn, &analyzeFn, &comment, &relkind, &collname); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read type %s.%s: %w\", schema, name, err)\n\t}\n\tif err := rows.Close(); err != nil {\n\t\treturn nil, err\n\t}\n\tif !typisdefined {\n\t\treturn nil, fmt.Errorf(\"custom type %s.%s is not fully defined\", schema, name)\n\t}\n\tif typelem != 0 {\n\t\treturn nil, fmt.Errorf(\"custom type %s.%s is an array companion type\", schema, name)\n\t}\n\tkind, ok := customTypeKindFromCode(typtype)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"custom type %s.%s is a pseudo type (typtype=%s)\", schema, name, typtype)\n\t}\n\tif relkind.Valid && relkind.String != \"\" && relkind.String != \"c\" {\n\t\treturn nil, fmt.Errorf(\"%s.%s is the auto-generated row type of a relation, not an independent custom type\", schema, name)\n\t}\n\n\tproperties := customTypeCommonProperties(inputFn, outputFn, receiveFn, sendFn, analyzeFn, typlen, typbyval, typalign, typstorage)\n\tproperties.DomainConstraints = []customTypeDomainConstraint{}\n\tdetails := &customTypeDetails{\n\t\tName:       name,\n\t\tSchema:     schema,\n\t\tKind:       kind,","sourceCodeStart":617,"sourceCodeEnd":653,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/vastbase-go/vastbase_metadata.go#L617-L653","documentation":"The type row was found and scanned, but its typisdefined flag is false — the catalog entry for this type is a placeholder that is not fully defined, so the library refuses to produce details or DDL for it. PostgreSQL/Vastbase create such shells during partial type creation states; a fully usable custom type always has typisdefined = true.","triggerScenarios":"Calling getTypeDetails on a type whose catalog row has typisdefined=false; typically seen on types left behind by an interrupted CREATE TYPE, shell types created implicitly by CREATE FUNCTION referencing a not-yet-created type, or corrupted/partial catalog state after a failed migration.","commonSituations":"A migration that created shell types then failed before CREATE TYPE completed; DDL generated by tools that forward-declare types; restoring a dump partially; manually created stub entries while scaffolding I/O functions.","solutions":["Inspect the type: SELECT typname, typisdefined FROM pg_type WHERE oid='schema.name'::regclass-ish (use to_regtype); confirm typisdefined=false","Complete the type definition by re-running the full CREATE TYPE (including I/O functions for base types)","Drop the shell type (DROP TYPE IF EXISTS) and recreate it properly with its dependencies created first","Reorder migrations so all referenced types are fully created before this lookup runs"],"exampleFix":"// before\n-- migration only created a shell via function signature\ndetails, err := srv.getTypeDetails(\"public\", \"widget\") // not fully defined\n// after\n-- complete the type first\nCREATE TYPE public.widget AS (id int, name text);\ndetails, err := srv.getTypeDetails(\"public\", \"widget\")","handlingStrategy":"validation","validationCode":"-- ensure defined before lookup\nSELECT typisdefined FROM pg_type t JOIN pg_namespace n ON n.oid=t.typnamespace WHERE n.nspname=$1 AND t.typname=$2;","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"not fully defined\") { /* recreate the type */ }","preventionTips":["Run complete CREATE TYPE statements atomically","Clean up shell types after failed migrations"],"tags":["postgres","metadata","incomplete-type","catalog"],"backgroundTag":"type-not-fully-defined","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}