jmoiron/sqlx · error
unexpected `:` while reading named param at
Error message
unexpected `:` while reading named param at
What it means
When compiling a named query, sqlx treats ':' as the start of a named parameter (:name). A second ':' encountered while still inside a parameter name is only legal as the PostgreSQL cast escape '::'. Any other unexpected ':' inside a name (e.g. '::' logic confusion or ':a:b') means the named syntax is malformed, so compilation fails with this error including the byte offset.
Source
Thrown at named.go:349
func compileNamedQuery(qs []byte, bindType int) (query string, names []string, err error) {
names = make([]string, 0, 10)
rebound := make([]byte, 0, len(qs))
inName := false
last := len(qs) - 1
currentVar := 1
name := make([]byte, 0, 10)
for i, b := range qs {
// a ':' while we're in a name is an error
if b == ':' {
// if this is the second ':' in a '::' escape sequence, append a ':'
if inName && i > 0 && qs[i-1] == ':' {
rebound = append(rebound, ':')
inName = false
continue
} else if inName {
err = errors.New("unexpected `:` while reading named param at " + strconv.Itoa(i))
return query, names, err
}
inName = true
name = []byte{}
} else if inName && i > 0 && b == '=' && len(name) == 0 {
rebound = append(rebound, ':', '=')
inName = false
continue
// if we're in a name, and this is an allowed character, continue
} else if inName && (unicode.IsOneOf(allowedBindRunes, rune(b)) || b == '_' || b == '.') && i != last {
// append the byte to the name if we are in a name and not on the last byte
name = append(name, b)
// if we're in a name and it's not an allowed character, the name is done
} else if inName {
inName = false
// if this is the final byte of the string and it is part of the name, then
// make sure to add it to the name
if i == last && unicode.IsOneOf(allowedBindRunes, rune(b)) {View on GitHub (pinned to 41dac167fd)
Solutions
- Fix the query so each ':' begins a valid name followed by alphanumerics and ends cleanly
- Escape a literal '::' cast properly (sqlx handles '::' — ensure there is no stray single ':' before it)
- Rename params so none contain ':' inside the name (e.g. :from_date not :from:date)
- Use '?' positional binding with sqlx.In if the query needs complex placeholder syntax
Example fix
// before q := "SELECT * FROM t WHERE created::date = :day AND ts:::tz IS NULL" // after q := "SELECT * FROM t WHERE created::date = :day AND ts::timestamptz IS NULL"
Defensive patterns
Strategy: validation
Validate before calling
func validateNamedParams(query string) error {
for i := 0; i < len(query); i++ {
if query[i] == ':' {
if i+1 < len(query) && query[i+1] == ':' { i++; continue } // :: cast
j := i + 1
for j < len(query) && (query[j] == '_' || isAlnum(query[j])) { j++ }
if j == i+1 { return fmt.Errorf("empty named param at %d", i) }
if j < len(query) && query[j] == ':' { return fmt.Errorf("unexpected ':' after param at %d", j) }
i = j - 1
}
}
return nil
} Try / catch
query, args, err := db.PrepareNamed(q)
if err != nil {
if strings.Contains(err.Error(), "unexpected `:`") {
log.Printf("malformed named param near offset in %s", q)
}
return err
} Prevention
- Only use :: escapes for PostgreSQL casts; avoid other double-colon sequences
- Never embed ':' inside parameter names
- Lint queries for stray ':' characters before runtime
When it happens
Trigger: Calling NamedQuery/PrepareNamed/Get/Select with a query containing malformed named params like ":a:b", or a lone ':' immediately after an incomplete name, where compileNamedQuery's inName state meets another ':' that isn't part of '::'.
Common situations: Mixing PostgreSQL casts (::type) with named params and mis-escaping; accidentally writing two adjacent named params without text between them; porting queries from other libraries with different placeholder syntaxes.
Related errors
- empty slice passed to 'in' query
- number of bindVars exceeds arguments
- number of bindVars less than number arguments
- sql: RawBytes isn't allowed on Row.Scan
- must pass a pointer, not a value, to StructScan destination
AI-assisted analysis of jmoiron/sqlx@41dac167fd (2026-09-03).
Data as JSON: /api/errors/34aa2818a1523d1f.
Report an issue: GitHub.