Skip to content

Bugfix Issue 1735 reqSpecSearch count null 500

opencode agent edited this page Oct 10, 2026 · 1 revision

Bug fix — Issue #1735: reqSpecSearch.php:116 count() on an uninitialised $itemSet — HTTP 500 / 0 bytes

The legacy Search → Requirement Specification Results screen (lib/requirements/reqSpecSearch.php) answered HTTP 500 with a 0-byte body because of

Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, null given
  in …/lib/requirements/reqSpecSearch.php:116

$gui->row_qty=count($itemSet); sat outside the only block that assigns $itemSet, so any state that skips that block makes count(null) a PHP-8 TypeError. On 1.9.20 (PHP 5.x) the same expression was only a warning and still rendered an empty table.

Resolution — already retired by #1825 (no new code)

The controller that contained the defect was deleted when this screen was modernized:

  • d1b2a884c — feat(#1825): retire both legacy req-spec search controllers + switch the link (2026-10-04) turned lib/requirements/reqSpecSearch.php into a session-guarded redirect shim;
  • 7e859c3b9 — follow-up hardening.

The screen is now the Dashio page Search Requirement Specifications backed by api/requirements/index.php (GET /reqspec-search), whose counter is initialised (:2176 $count = 0;) — count(null) cannot occur — and whose empty state is the explicit else { $warning = 'no_records_found'; } (:2212-2214), exactly the behaviour the issue's Expected section asked for.

Search Requirement Specifications — modern replacement (issue #1735)

Search results render, no HTTP 500 (issue #1735)

Measured evidence

Current default branch (bce8fb392):

$ curl ... "$BASE/lib/requirements/reqSpecSearch.php"
HTTP 302 size=0 redirect=…/gui/templates/requirements/searchReqSpec.html?tproject_id=1

# XHR flavour
HTTP 405 size=170
{"status":"error","code":"retired_endpoint","message":"This legacy endpoint no longer serves the search results. …"}

$ curl ... "$BASE/api/requirements/index.php/reqspec-search?tproject_id=1"
HTTP 200 {"status":"ok","count":2,"rows":[…],"warning":"" …}

Discrimination — restoring the pre-#1825 controller and probing as a user with no session project reproduces the 500 (testproject::get_by_id(0) in reqSpecCommands::__construct, reached from reqSpecSearch.php:34); with a project set the same pre-fix file reaches count($itemSet) at line 116.

Root cause

hop file:line (pre-#1825) code
1 reqSpecSearch.php:43 $itemSet = null;
2 reqSpecSearch.php:104 if($args->tprojectID) { … } — the only block assigning $itemSet
3 reqSpecSearch.php:113 $itemSet = $db->fetchRowsIntoMap(…)
4 reqSpecSearch.php:116 $gui->row_qty=count($itemSet); — unconditional → TypeError

Blast radius / why no re-patch

reference status
lib/requirements/reqSpecSearch.php redirect shim only
gui/templates/{dashio,tl-classic}/requirements/reqSpecSearchForm.tpl:25 dead legacy form action (screen no longer rendered; modern action …/reqSpecSearchForm.html, lib/general/frmWorkArea.php:34)
lib/functions/tlReqMgrSystem.class.php:673, api/requirements/index.php:2095 comments only

Re-patching count($itemSet) would keep a second redundant search implementation alive behind a page the ASIDE no longer links to; the retirement removes the whole class of PHP-8 defects from the path.

Verification

bash tmp/verify_1735.sh — self-cleaning, creates its own fixture, exits non-zero on any failure: 15 PASS / 0 FAIL (exit 0) — legacy URL 302/405 (never 500), modern screen 200, BFF results / filtered count / no_records_found, zero Event-Viewer Error/Warning rows, and no count($itemSet) in either the shim or the BFF.

Related

  • Issue #1629 — the sibling 500 fix that let the request reach this screen's own defect.
  • Issue #1825 — the modernization that retired this controller.

Clone this wiki locally