{"id":"b22e494bdb7c0441","repo":"psycopg/psycopg2","slug":"no-format-specification-supported-by-sql","errorCode":null,"errorMessage":"no format specification supported by SQL","messagePattern":"no format specification supported by SQL","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/sql.py","lineNumber":230,"sourceCode":"\n        Example::\n\n            >>> print(sql.SQL(\"select * from {} where {} = %s\")\n            ...     .format(sql.Identifier('people'), sql.Identifier('id'))\n            ...     .as_string(conn))\n            select * from \"people\" where \"id\" = %s\n\n            >>> print(sql.SQL(\"select * from {tbl} where {pkey} = %s\")\n            ...     .format(tbl=sql.Identifier('people'), pkey=sql.Identifier('id'))\n            ...     .as_string(conn))\n            select * from \"people\" where \"id\" = %s\n\n        \"\"\"\n        rv = []\n        autonum = 0\n        for pre, name, spec, conv in _formatter.parse(self._wrapped):\n            if spec:\n                raise ValueError(\"no format specification supported by SQL\")\n            if conv:\n                raise ValueError(\"no format conversion supported by SQL\")\n            if pre:\n                rv.append(SQL(pre))\n\n            if name is None:\n                continue\n\n            if name.isdigit():\n                if autonum:\n                    raise ValueError(\n                        \"cannot switch from automatic field numbering to manual\")\n                rv.append(args[int(name)])\n                autonum = None\n\n            elif not name:\n                if autonum is None:\n                    raise ValueError(","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/psycopg/psycopg2/blob/3a6d9d6ddc6b53eaa80b712f5fa6b23abbdc38db/lib/sql.py#L212-L248","documentation":"Raised by SQL.format() (lib/sql.py:230) when a placeholder in the SQL template carries a format specification, i.e. the part after a colon like {0:<10} or {0:d}. psycopg2 intentionally implements only a restricted subset of str.format: it uses placeholders purely to splice Composable objects, so alignment/width/type specs are meaningless and rejected. The whole template is parsed up front via string.Formatter().parse() and any non-empty spec triggers this ValueError before any composition happens.","triggerScenarios":"Calling sql.SQL(...).format(...) where the template string contains a colon-specifier, e.g. sql.SQL(\"select {0:<10}\").format(sql.Identifier('x')), sql.SQL(\"{n:>20}\").format(n=...), or any placeholder of the form {name:spec} / {idx:spec}.","commonSituations":"Copying a Python f-string or str.format template that used padding/alignment or numeric formatting (logging, report code) and pasting it into sql.SQL(...) without stripping the spec. Misunderstanding that SQL.format is a deliberately limited version of str.format.","solutions":["Remove the ':spec' portion from every placeholder in the SQL template (e.g. {0:<10} -> {0}, {n:>20} -> {n}).","If padding/transform is genuinely needed, apply it to the rendered string after as_string() returns, never inside the template.","Render Python values as SQL literals with sql.Literal and do any Python-side formatting before wrapping them."],"exampleFix":"// before\nquery = sql.SQL(\"select {0:<10} from tbl\").format(sql.Identifier('col'))\n// after\nquery = sql.SQL(\"select {} from tbl\").format(sql.Identifier('col'))","handlingStrategy":"validation","validationCode":"import string\n\ndef sql_template_is_clean(template: str) -> bool:\n    \"\"\"True if no placeholder carries a format spec or conversion.\"\"\"\n    for _pre, _name, spec, conv in string.Formatter().parse(template):\n        if spec or conv:\n            return False\n    return True\n\n# use before building the SQL:\nassert sql_template_is_clean(tpl), f'bad SQL template: {tpl!r}'\nq = sql.SQL(tpl).format(...)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat sql.SQL templates as a restricted mini-language: only {}, {0}, {name} - never :spec or !conv.","Run a one-line Formatter().parse() scan in CI/lint over SQL template literals.","Pre-build templates once and unit-test that .format(...) succeeds with sample Composables."],"tags":["psycopg2","sql-composition","format","valueerror"],"analyzedSha":"3a6d9d6ddc6b53eaa80b712f5fa6b23abbdc38db","analyzedAt":"2026-08-04T19:56:51.958Z","schemaVersion":2}