Skip to content

Log search returns wrong results: message filter is case-sensitive, and '% / _' are treated as wildcards #2

Description

@huzaif-fahad

What happened

Two problems with how the containment filters build their LIKE patterns. Both return the wrong rows silently; no error, no log line, the query just answers something other than what was asked.
1. Free-text log search is case-sensitive.

internal/adapters/db/log_repo.go:150 uses LIKE where every other text filter in the file uses ILIKE:

query = query.Where("message LIKE ?", "%"+f.TextQuery+"%")

Compare :110 and :116 a few lines above, which are ILIKE, and :623, which has the comment "nobody types a path with the case they logged it in" - the same reasoning applies to messages. Searching error does not find
Error: upload failed, so any message that starts a sentence is invisible to the obvious search for it.

2. % and _ in the search box are treated as wildcards

The pattern is "%"+text+"%" with nothing escaped, at six call sites:

File Line Filter
internal/adapters/db/log_repo.go 110 device_model
internal/adapters/db/log_repo.go 116 os_name / os_version
internal/adapters/db/log_repo.go 150 message (free text)
internal/adapters/db/log_repo.go 623 url (network path)
internal/adapters/db/project_repo.go 267 projects.name

So searching 100% matches every message containing 100, and user_id also matches userXid. Both are ordinary characters to whoever typed them.

Worth noting the Flutter side already gets this right — sqflite_source.dart escapes \, % and _ and passes an explicit ESCAPE '\'. This is the same fix on the server.

Suggested fix: one helper in internal/adapters/db, used at all six sites, plus LIKEILIKE on line 150:

var likeWildcards = strings.NewReplacer(`\`, `\\`, `%`, `\%`, `_`, `\_`)

func containsPattern(s string) string {
	return "%" + likeWildcards.Replace(s) + "%"
}

with each call becoming col ILIKE ? ESCAPE '\'. Backslash is already Postgres's default escape character, so the clause is documentation rather than a behaviour change.

How to reproduce it

  1. Create a project and upload a batch containing these messages:
    • Error: upload failed
    • battery at 100% before sync
    • battery at 1004 mAh
    • missing user_id on request
    • missing userXid on request
  2. Open the log viewer and search error
    → expected Error: upload failed, got nothing.
  3. Search 100%
    → expected only battery at 100% before sync, got that plus battery at 1004 mAh.
  4. Search user_id
    → expected only missing user_id on request, got that plus missing userXid on request.

Version

749f973 (main, 2026-08-12)

Server log

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggood first issueGood for newcomers

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions