{"record":{"id":"db05545b11ff4bd2","repo":"gastownhall/beads","slug":"identifier-too-long-q-max-d-chars","errorCode":null,"errorMessage":"identifier too long: %q (max %d chars)","messagePattern":"identifier too long: %q \\(max (.+?) chars\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/ddl.go","lineNumber":17,"sourceCode":"package db\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"regexp\"\n)\n\nvar validIdentifier = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)\n\nconst maxIdentifierLength = 64\n\n// ValidateIdentifier checks whether name is safe to use, unquoted, as a\n// database or table identifier in this package's DDL statements.\nfunc ValidateIdentifier(name string) error {\n\tif len(name) > maxIdentifierLength {\n\t\treturn fmt.Errorf(\"identifier too long: %q (max %d chars)\", name, maxIdentifierLength)\n\t}\n\tif !validIdentifier.MatchString(name) {\n\t\treturn fmt.Errorf(\"invalid identifier: %q\", name)\n\t}\n\treturn nil\n}\n\ntype DDLSQLRepository interface {\n\tCreateDatabaseIfNotExists(ctx context.Context, database string) error\n\t// CreateDatabase issues a bare CREATE DATABASE (no IF NOT EXISTS) so the\n\t// server arbitrates creation atomically: success proves this call created\n\t// the database; an already-exists error (MySQL 1007) proves it did not.\n\t// The error is returned unmapped (wrapped with %w) so callers can\n\t// classify it against their driver.\n\tCreateDatabase(ctx context.Context, database string) error\n\tUseDatabase(ctx context.Context, database string) error\n}\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/ddl.go#L1-L35","documentation":"ValidateIdentifier rejects identifiers longer than 64 characters, matching the MySQL/Dolt identifier length limit, before they are used in DDL statements. This error means the supplied database or table name exceeds that limit and would be rejected (or truncated) by the server. It is surfaced to callers via QuoteIdentifier and wrappers like db: CreateDatabaseIfNotExists.","triggerScenarios":"Calling CreateDatabaseIfNotExists, CreateDatabase, or UseDatabase with a database name whose length exceeds 64 characters (byte length of the string), or any code path that calls QuoteIdentifier/ValidateIdentifier with an over-long name.","commonSituations":"Programmatically derived database names (tenant IDs, hashed tokens, long project slugs) concatenated into names exceeding 64 chars; misconfigured BD_ or env-derived database names.","solutions":["Shorten the database name to 64 characters or fewer before calling the DDL API.","Derive names from shorter, stable inputs (project key or short hash) instead of full IDs/URLs.","Pre-check names with db.ValidateIdentifier(name) to fail fast with a clear message.","Fix the configuration/environment variable supplying the over-long name."],"exampleFix":"// before\nerr := ddl.CreateDatabaseIfNotExists(ctx, \"beads-\"+longTenantUUID+\"-production-us-east\")\n// after\nname := \"beads-\" + shortHash(longTenantUUID) // <= 64 chars\nif err := db.ValidateIdentifier(name); err != nil { return err }\nerr := ddl.CreateDatabaseIfNotExists(ctx, name)","handlingStrategy":"validation","validationCode":"func checkDBName(name string) error {\n    if len(name) > 64 {\n        return fmt.Errorf(\"database name %q exceeds 64 chars (len=%d)\", name, len(name))\n    }\n    return db.ValidateIdentifier(name)\n}","typeGuard":"func validName(name string) bool {\n    return len(name) <= 64 && regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`).MatchString(name)\n}","tryCatchPattern":"if err := db.ValidateIdentifier(name); err != nil {\n    return fmt.Errorf(\"refusing DDL with bad name: %w\", err)\n}\nerr := ddl.CreateDatabaseIfNotExists(ctx, name)","preventionTips":["Cap derived database names at 64 characters using short hashes of long inputs.","Run ValidateIdentifier on every name sourced from config or environment before DDL calls.","Never concatenate raw user/tenant IDs into database names."],"tags":["validation","identifier","ddl"],"backgroundTag":"identifier-validation-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}