Ticket create 500s when group_id is submitted as a JSON array #10
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
POST /app/ticketing(the ticket-create endpoint,ticketing.store) throws anunhandled 500 when
group_idis submitted as a JSON array instead of a scalarinteger, instead of returning a normal 422 validation error.
Steps to reproduce
Logged in as
superadmin@playwright.test. From a browser session onhttps://central-dev.vancs.org/app/ticketing/create(so cookies/XSRF token arevalid), issue:
(
14is the id of the real "General" ticketing group in this dev environment —substitute any id that actually exists.)
Expected
A 422 with a validation error on
group_id(e.g. "The group id field must bean integer."), the same way
group_id: ['a','b'](an array of values thatdon't exist) correctly returns:
Actual
A 500 with no further detail leaked (APP_DEBUG appears to be off — response
body is just
{"message":"Server Error"}, no stack trace):Analysis
Laravel's
existsvalidation rule, when given an array value for the field,validates that every element of the array exists in the table — this is
normally intended for multi-select fields. Since
14really is a valid groupid,
group_id: [14]passes theexistscheck as an array of one valid id,so validation lets it through. The controller then presumably treats
$request->group_idas a scalar (e.g. passes it straight into a query or anintcolumn), and something downstream (an array where an int/scalar wasexpected) throws, producing the 500.
A value made entirely of non-existent entries (
['a','b']) is correctlyrejected by the
existscheck itself before reaching that code, which is whyonly some array shapes reproduce this specifically.
Suggested fix
Add an explicit
integer(orsometimes|integer) rule ahead ofexistsongroup_idin the ticket-store request validation, so a non-scalar value isrejected with a normal 422 before ever reaching the
existscheck or thecontroller.
Environment
https://central-dev.vancs.org/app/ticketing(POST)superadmin@playwright.testticketing.store(confirmed viaroute().current()→ticketing.indexprefixticketing)robustness/crash bug, not an information-disclosure bug.
Filed automatically by the Claude-driven QA sweep (
/opt/qa-agent). The marker below dedupes repeat reports — do not edit it.Fixed in
afbbd3f.Your analysis was right:
existsgiven an array validates that every element exists, sogroup_id: [14]passed with one valid id and reached the controller as an array —findOrFail()returned a Collection and->nextTicketNumber()on it fatalled.["a","b"]was rejected byexistsitself, which is why only arrays of valid ids reproduced it.Added
integerahead ofexistsas you suggested, but the hole is a property ofexistsrather than of group_id, so all nine id fields across both ticketing controllers had it —store()group_id/priority_id,update()priority_id/project_id/group_id, and storeAgent/storeProject/storeEmailConnection group_id plus user_id (which fed straight into an access check).Tests pin the repro, the same thing on priority_id, that a nonexistent id still 422s, and that a normal scalar create still works. Confirmed the array test fails with the rules reverted.