{"record":{"id":"7b326ba037647e6d","repo":"PHPOffice/PhpSpreadsheet","slug":"cannot-check-for-hyperlink-when-cell-is-not-bound","errorCode":null,"errorMessage":"Cannot check for hyperlink when cell is not bound to a worksheet","messagePattern":"Cannot check for hyperlink when cell is not bound to a worksheet","errorType":"exception","errorClass":"SpreadsheetException","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Cell/Cell.php","lineNumber":777,"sourceCode":"    /**\n     * Does this cell contain valid value?\n     */\n    public function hasValidValue(): bool\n    {\n        $validator = new DataValidator();\n\n        return $validator->isValid($this);\n    }\n\n    /**\n     * Does this cell contain a Hyperlink?\n     *\n     * @throws SpreadsheetException\n     */\n    public function hasHyperlink(): bool\n    {\n        if (!isset($this->parent)) {\n            throw new SpreadsheetException('Cannot check for hyperlink when cell is not bound to a worksheet');\n        }\n\n        return $this->getWorksheet()->hyperlinkExists($this->getCoordinate());\n    }\n\n    /**\n     * Get Hyperlink.\n     *\n     * @throws SpreadsheetException\n     */\n    public function getHyperlink(): Hyperlink\n    {\n        if (!isset($this->parent)) {\n            throw new SpreadsheetException('Cannot get hyperlink for cell that is not bound to a worksheet');\n        }\n\n        return $this->getWorksheet()\n            ->getHyperlink($this->getCoordinate());","sourceCodeStart":759,"sourceCodeEnd":795,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Cell/Cell.php#L759-L795","documentation":"hasHyperlink() checks $this->parent first because hyperlink existence is stored per coordinate on the worksheet (Worksheet::hyperlinkExists()). A Cell no longer bound to a worksheet cannot be looked up, so the method throws instead of returning false - important distinction: this is a lifecycle error, not 'no hyperlink here'.","triggerScenarios":"Calling hasHyperlink() on a Cell retained after removeSheetByIndex(), unset($spreadsheet), or after the Cells collection was detached from its worksheet.","commonSituations":"Link-scraping/auditing passes that walk harvested Cell objects; serialization queues where Cell references outlive the workbook.","solutions":["Query the worksheet directly: $sheet->hyperlinkExists($coord)","Guard with $cell->getParent() !== null (or getWorksheetOrNull() !== null) before the call","Store coordinate strings and refetch cells from a live sheet"],"exampleFix":"// before\n$has = $cell->hasHyperlink(); // throws when detached\n\n// after\n$has = $sheet->hyperlinkExists('A1');","handlingStrategy":"validation","validationCode":"if ($sheet !== null) {\n    $has = $sheet->hyperlinkExists($coord);\n} elseif ($cell->getParent() !== null) {\n    $has = $cell->hasHyperlink();\n} else {\n    $has = false;\n}","typeGuard":"function canQueryCellState(Cell $cell): bool\n{\n    return $cell->getParent() !== null;\n}","tryCatchPattern":"null","preventionTips":["Query hyperlinks via Worksheet::hyperlinkExists($coordinate) when possible","Audit links while the workbook is still assembled, not from stale Cell references","Guard any Cell method that needs a worksheet with a getParent() check first"],"tags":["phpspreadsheet","cell","hyperlink","detached-object","worksheet"],"backgroundTag":"detached-object-access","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}