{"record":{"id":"2bd3098be5932340","repo":"multica-ai/multica","slug":"empty-component-in-q","errorCode":null,"errorMessage":"empty component in %q","messagePattern":"empty component in %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/migrate/main.go","lineNumber":479,"sourceCode":"// into a SQL statement. Postgres does not let parametrized queries\n// supply identifiers, so we have to interpolate, but pgx.Identifier\n// does the right escaping (double-quotes, embedded-quote handling).\n//\n// The accepted shape is exactly one or two dot-separated components.\n// Names containing more than one dot are rejected outright rather than\n// silently sanitized into a \"schema\".\"b.c\" reference, which is valid\n// SQL but almost certainly not what the caller meant.\nfunc quoteQualifiedIdentifier(name string) (string, error) {\n\tif name == \"\" {\n\t\treturn \"\", fmt.Errorf(\"empty identifier\")\n\t}\n\tparts := strings.Split(name, \".\")\n\tif len(parts) > 2 {\n\t\treturn \"\", fmt.Errorf(\"identifier %q has more than one dot; only schema.table is supported\", name)\n\t}\n\tfor _, p := range parts {\n\t\tif p == \"\" {\n\t\t\treturn \"\", fmt.Errorf(\"empty component in %q\", name)\n\t\t}\n\t}\n\treturn pgx.Identifier(parts).Sanitize(), nil\n}\n","sourceCodeStart":461,"sourceCodeEnd":484,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/migrate/main.go#L461-L484","documentation":"quoteQualifiedIdentifier splits on \".\" and rejects any empty component, catching degenerate names like \"issues.\", \".issues\", or \".\" that would otherwise sanitize to an empty quoted component (\"issues\".\"\"), which is invalid or points nowhere.","triggerScenarios":"Passing a name with a leading/trailing dot or a bare dot: \"schema.\", \".table\", \".\", or strings produced by joining empty parts with dots.","commonSituations":"fmt.Sprintf(\"%s.%s\", schema, table) with one variable empty; config values written as \"workspace.\" with a trailing dot; strings.Split output reassembled without filtering empties.","solutions":["Print/inspect the offending value (the %q in the message shows it exactly) and fix the empty side.","Require both schema and table at the source — validate flags/config before composing the name.","If schema is optional, only prefix the dot when the schema part is non-empty."],"exampleFix":"// before\nname := fmt.Sprintf(\"%s.%s\", schema, table) // schema == \"\" -> \".issues\"\n\n// after\nvar name string\nif schema != \"\" {\n    name = schema + \".\" + table\n} else {\n    name = table\n}","handlingStrategy":"validation","validationCode":"func joinTable(schema, table string) (string, error) {\n    if table == \"\" {\n        return \"\", fmt.Errorf(\"table component is required\")\n    }\n    if schema == \"\" {\n        return table, nil\n    }\n    return schema + \".\" + table, nil\n}","typeGuard":"func hasNoEmptyComponent(name string) bool {\n    for _, p := range strings.Split(name, \".\") {\n        if p == \"\" {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"q, err := quoteQualifiedIdentifier(name)\nif err != nil {\n    return fmt.Errorf(\"bad identifier %q (empty component): %w\", name, err)\n}","preventionTips":["Only concatenate the schema prefix when the schema part is non-empty.","Trim and check both halves when composing names from config variables.","Unit-test identifier helpers with table-driven cases including \".table\", \"table.\", and \".\"."],"tags":["go","validation","sql","identifiers"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}