Bug description
When a printer doesn't appear in FloCafe's auto-detected list and a user adds it manually by typing the name exactly as it appears on their PC, the test print silently fails (or times out) with a generic error — because the manually-typed name frequently cannot match the real OS print queue identifier, and the app never validates or warns about this at entry time.
Steps to reproduce
- Open Settings → Printers.
- Printer isn't in the auto-detected list (common for printers with special characters in their queue name, or added after FloCafe was last opened).
- Add manually, typing the name as shown on the OS (e.g.
"POS-58 (Copy 1)" or a printer with a localized/non-ASCII name).
- Send a test print.
Expected behavior
Either the test print succeeds, or the app clearly explains why the typed name doesn't match a real printer.
Actual behavior
Test print fails with a generic "Test print failed" toast, or silently does nothing. No indication is given that the name itself is the problem.
Root cause
1. The manual-add field is validated against an overly strict pattern that rejects common real-world OS printer names, and against nothing else:
// main/routes/printers.ts:23
const PRINTER_NAME_REGEX = /^[a-zA-Z0-9 _\-\.]+$/;
This rejects parentheses, commas, colons, slashes, and any non-ASCII characters — all of which show up in real Windows/CUPS queue names (e.g. "POS-58 (Copy 1)", "Generic / Text Only", non-Latin printer names). A user who types the exact name from their PC is frequently rejected and has to approximate it — guaranteeing every later print attempt fails, since dispatch requires an exact match:
- macOS/Linux:
printViaCups() (main/printers/thermal.ts:1760-1789) runs lp -d <printerName>. CUPS also silently converts spaces in queue names to underscores in some install paths, so even the visible display name can differ from the real queue name.
- Windows:
printViaUSBWindows() (main/printers/thermal.ts:1997-2040) calls OpenPrinterW(printerName, ...), which fails outright on any mismatch with no fuzzy matching. Neither the frontend nor validatePrinterFields in main/routes/printers.ts trims leading/trailing whitespace from name, either.
2. The one-click "Installed on this computer" quick-add flow does this correctly today (quickAddDetected, frontend/src/app/(dashboard)/settings/page.tsx:851-878), reusing the exact string from GET /printers/detect (main/printers/thermal.ts:137-157) — it's specifically the free-text manual-entry path that's unguarded.
3. Errors are swallowed client-side, so even the diagnosable failures produce no useful signal:
// frontend/src/app/(dashboard)/settings/page.tsx:945-958 (testPrinterHw)
catch { toast.error(t('testPrintFailed')); }
This discards result.detail, which the /test backend route already returns (main/routes/printers.ts:321).
Proposed fix
- Loosen
PRINTER_NAME_REGEX (main/routes/printers.ts:23) to allow the realistic character set used by OS printer queue names, while still blocking shell metacharacters actually used for injection (the comment says the intent is "no shell metacharacters" — the current regex is far stricter than that goal requires). Trim whitespace on save.
- In the manual-add form (
settings/page.tsx:794-805, 3800-3806), surface the live auto-detected list as an autocomplete/datalist so users are steered toward exact matches instead of free-typing, and show a warning when a typed name doesn't match anything in GET /printers/detect.
- Fix
testPrinterHw (settings/page.tsx:945-958) and savePrinterHw (settings/page.tsx:897-924) to surface the backend's detail field instead of a generic toast.
- Update
docs/printers.md:54-67 to explicitly document that manually-typed names must match the OS queue identifier exactly, not the display name.
Related: #<ISSUE_1_NUMBER> (the same name-mismatch, once a printer is saved, then produces "Print failed. Check printer connection and settings." on every subsequent real order/KOT print — that issue covers surfacing the diagnostic on those routes).
Environment
Affects users on all platforms who add a printer manually because auto-detection didn't find it.
Bug description
When a printer doesn't appear in FloCafe's auto-detected list and a user adds it manually by typing the name exactly as it appears on their PC, the test print silently fails (or times out) with a generic error — because the manually-typed name frequently cannot match the real OS print queue identifier, and the app never validates or warns about this at entry time.
Steps to reproduce
"POS-58 (Copy 1)"or a printer with a localized/non-ASCII name).Expected behavior
Either the test print succeeds, or the app clearly explains why the typed name doesn't match a real printer.
Actual behavior
Test print fails with a generic "Test print failed" toast, or silently does nothing. No indication is given that the name itself is the problem.
Root cause
1. The manual-add field is validated against an overly strict pattern that rejects common real-world OS printer names, and against nothing else:
This rejects parentheses, commas, colons, slashes, and any non-ASCII characters — all of which show up in real Windows/CUPS queue names (e.g.
"POS-58 (Copy 1)","Generic / Text Only", non-Latin printer names). A user who types the exact name from their PC is frequently rejected and has to approximate it — guaranteeing every later print attempt fails, since dispatch requires an exact match:printViaCups()(main/printers/thermal.ts:1760-1789) runslp -d <printerName>. CUPS also silently converts spaces in queue names to underscores in some install paths, so even the visible display name can differ from the real queue name.printViaUSBWindows()(main/printers/thermal.ts:1997-2040) callsOpenPrinterW(printerName, ...), which fails outright on any mismatch with no fuzzy matching. Neither the frontend norvalidatePrinterFieldsinmain/routes/printers.tstrims leading/trailing whitespace fromname, either.2. The one-click "Installed on this computer" quick-add flow does this correctly today (
quickAddDetected,frontend/src/app/(dashboard)/settings/page.tsx:851-878), reusing the exact string fromGET /printers/detect(main/printers/thermal.ts:137-157) — it's specifically the free-text manual-entry path that's unguarded.3. Errors are swallowed client-side, so even the diagnosable failures produce no useful signal:
This discards
result.detail, which the/testbackend route already returns (main/routes/printers.ts:321).Proposed fix
PRINTER_NAME_REGEX(main/routes/printers.ts:23) to allow the realistic character set used by OS printer queue names, while still blocking shell metacharacters actually used for injection (the comment says the intent is "no shell metacharacters" — the current regex is far stricter than that goal requires). Trim whitespace on save.settings/page.tsx:794-805, 3800-3806), surface the live auto-detected list as an autocomplete/datalist so users are steered toward exact matches instead of free-typing, and show a warning when a typed name doesn't match anything inGET /printers/detect.testPrinterHw(settings/page.tsx:945-958) andsavePrinterHw(settings/page.tsx:897-924) to surface the backend'sdetailfield instead of a generic toast.docs/printers.md:54-67to explicitly document that manually-typed names must match the OS queue identifier exactly, not the display name.Related: #<ISSUE_1_NUMBER> (the same name-mismatch, once a printer is saved, then produces "Print failed. Check printer connection and settings." on every subsequent real order/KOT print — that issue covers surfacing the diagnostic on those routes).
Environment
Affects users on all platforms who add a printer manually because auto-detection didn't find it.