{"record":{"id":"f08ab40ba50ffda7","repo":"vitessio/vitess","slug":"unsupported-format-specifier-c","errorCode":null,"errorMessage":"unsupported format specifier: %%%c","messagePattern":"unsupported format specifier: %%%c","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/datetime/strftime.go","lineNumber":47,"sourceCode":"\t\tif i < 0 {\n\t\t\texec(&fmtVerbatim{s: p})\n\t\t\tbreak\n\t\t}\n\t\tif i == l-1 {\n\t\t\treturn errors.New(`stray %% at the end of pattern`)\n\t\t}\n\n\t\t// we found a '%'. we need the next byte to decide what to do next\n\t\t// we already know that i < l - 1\n\t\t// everything up to the i is verbatim\n\t\tif i > 0 {\n\t\t\texec(&fmtVerbatim{s: p[:i]})\n\t\t\tp = p[i:]\n\t\t}\n\n\t\tif spec, ok := ds[p[1]]; ok {\n\t\t\tif spec == nil {\n\t\t\t\treturn fmt.Errorf(`unsupported format specifier: %%%c`, p[1])\n\t\t\t}\n\t\t\texec(spec)\n\t\t} else {\n\t\t\texec(&fmtVerbatim{s: p[1:2]})\n\t\t}\n\t\tp = p[2:]\n\t}\n\treturn nil\n}\n\n// Format takes the format `p` and the time `t` to produce the\n// format date/time. Note that this function re-compiles the\n// pattern every time it is called.\n//\n// If you know beforehand that you will be reusing the pattern\n// within your application, consider creating a `Strftime` object\n// and reusing it.\nfunc Format(p string, t DateTime, prec uint8) ([]byte, error) {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/datetime/strftime.go#L29-L65","documentation":"The strftime-style formatter in go/mysql/datetime encountered a `%` specifier whose conversion character is not present in the supported specifiers table (or maps to nil). Since the format string is user-supplied, the library refuses to silently emit a wrong value and returns an error describing the unsupported specifier.","triggerScenarios":"Calling datetime Format/New (compile step) with a format string containing `%%c` where the character after `%` is not one of the supported strftime specifiers — e.g. `%K`, `%J`, or a literal `%` followed by a non-specifier letter.","commonSituations":"Users porting DATE_FORMAT/STRFTIME format strings from other databases or languages (Python strftime, C strftime) that support specifiers this implementation does not; typos in format templates stored in application config; locale-specific formats containing unsupported directives.","solutions":["Replace the unsupported specifier with one from the supported set in go/mysql/datetime (e.g. use %s/%f/%T style equivalents or compute the piece in SQL).","Escape the percent sign if a literal `%` followed by that character is intended, per the format's escaping rules.","Pre-validate user-supplied format strings against the supported specifier list before passing them to the formatter.","If the specifier is legitimately needed, add it to the `ds` specifiers map with a formatter implementation."],"exampleFix":"// before\nFormat(\"%Y-%m-%d %K\") // %K unsupported\n\n// after\nFormat(\"%Y-%m-%d %H:%i:%s\")","handlingStrategy":"validation","validationCode":"var supported = map[byte]bool{'Y': true, 'm': true, 'd': true, 'H': true, 'i': true, 's': true /* full set from datetime package */}\nfunc validFormat(f string) bool {\n    for i := 0; i < len(f); i++ {\n        if f[i] == '%' {\n            if i+1 >= len(f) || !supported[f[i+1]] {\n                return false\n            }\n            i++\n        }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":"out, err := dt.Format(layout, t)\nif err != nil {\n    if strings.Contains(err.Error(), \"unsupported format specifier\") {\n        out, err = dt.Format(fallbackLayout, t)\n    }\n}","preventionTips":["Keep format templates in a validated constant set, not free user input.","When porting formats from other languages, map each specifier to the supported set first.","Add a unit test per format template used in production.","Escape literal percent signs per the format's rules."],"tags":["mysql","datetime","format-string","parsing"],"backgroundTag":"unsupported-format-specifier","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}