{"record":{"id":"a9087d2d544d6c28","repo":"bytebase/bytebase","slug":"function-q-signature-q-a9087d","errorCode":null,"errorMessage":"function %q signature %q","messagePattern":"function %q signature %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/schema/pg/walk_through_loader.go","lineNumber":870,"sourceCode":"\nfunc wtInstallFunction(cat *catalog.Catalog, obj *wtObjectEntry) error {\n\tfn := obj.funcMeta\n\tif fn.Definition != \"\" {\n\t\tnodes, err := omniparser.Parse(fn.Definition)\n\t\tif err == nil && nodes != nil && len(nodes.Items) == 1 {\n\t\t\tnode := nodes.Items[0]\n\t\t\tif raw, ok := node.(*ast.RawStmt); ok {\n\t\t\t\tnode = raw.Stmt\n\t\t\t}\n\t\t\tif parsed, ok := node.(*ast.CreateFunctionStmt); ok {\n\t\t\t\treturn cat.CreateFunctionStmt(parsed)\n\t\t\t}\n\t\t}\n\t}\n\t// Fallback: build from signature.\n\targTypes, err := wtParseFuncArgTypes(fn.Signature)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"function %q signature %q\", fn.Name, fn.Signature)\n\t}\n\tparams := make([]ast.Node, 0, len(argTypes))\n\tfor i, at := range argTypes {\n\t\ttn, err := wtTypeNameFromString(at)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"function %q arg %d\", fn.Name, i)\n\t\t}\n\t\tparams = append(params, &ast.FunctionParameter{\n\t\t\tArgType: tn,\n\t\t\tMode:    ast.FUNC_PARAM_IN,\n\t\t})\n\t}\n\tstmt := &ast.CreateFunctionStmt{\n\t\tFuncname:   wtQualifiedList(obj.schema, fn.Name),\n\t\tReturnType: wtPseudoTextTypeName(),\n\t}\n\tif len(params) > 0 {\n\t\tstmt.Parameters = &ast.List{Items: params}","sourceCodeStart":852,"sourceCodeEnd":888,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/schema/pg/walk_through_loader.go#L852-L888","documentation":"This error is returned when the fallback path of wtInstallFunction cannot parse the function's argument types from fn.Signature. When the function body definition is absent or fails to parse as a CreateFunctionStmt, the loader falls back to rebuilding the signature, and wtParseFuncArgTypes failed on that string. The error is wrapped with the function name and signature for diagnosis.","triggerScenarios":"wtInstallReal installs a function entry whose funcMeta.Definition is empty or unparseable, forcing the signature fallback, and fn.Signature does not match the expected comma-separated type list format (e.g. contains DEFAULT values, OUT parameters, named args, or schema-qualified types the parser chokes on).","commonSituations":"Catalog dumps from Postgres with complex signatures (VARIADIC, table arguments, named parameters); fixtures with typos in the signature string; functions whose signature was recorded in a non-canonical format.","solutions":["Inspect fn.Signature and confirm it is a plain comma-separated list of type names like \"integer, text\"","Remove parameter names, defaults, and OUT/INOUT annotations from the signature; keep only input type names","If possible, fix the source so funcMeta.Definition contains a full CREATE FUNCTION statement that parses directly, bypassing the fallback","Verify each type name individually with wtTypeNameFromString to find the offending argument"],"exampleFix":"// before\nSignature: \"a integer DEFAULT 1, b text[]\"\n// after\nSignature: \"integer, text[]\"","handlingStrategy":"validation","validationCode":"func validFuncSignature(sig string) bool {\n\tif strings.TrimSpace(sig) == \"\" {\n\t\treturn false\n\t}\n\t_, err := wtParseFuncArgTypes(sig)\n\treturn err == nil\n}","typeGuard":null,"tryCatchPattern":"if err := wtInstallFunction(cat, obj); err != nil {\n\tif strings.Contains(err.Error(), \"signature\") {\n\t\tlog.Printf(\"function %s: bad signature %q: %v\", obj.funcMeta.Name, obj.funcMeta.Signature, err)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Keep signatures as plain comma-separated input type lists without names, defaults, or modes","Prefer storing a full CREATE FUNCTION definition so the signature fallback is never used","Normalize type names (use canonical spellings like numeric[] not _numeric) at dump time","Add a fixture test that parses every recorded signature with wtParseFuncArgTypes"],"tags":["postgres","function","signature","catalog"],"backgroundTag":"invalid-argument-format","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}