{"record":{"id":"4f5069a6915cce01","repo":"PHPOffice/PhpSpreadsheet","slug":"cannot-get-hyperlink-for-cell-that-is-not-bound-to","errorCode":null,"errorMessage":"Cannot get hyperlink for cell that is not bound to a worksheet","messagePattern":"Cannot get hyperlink for cell that is not bound to a worksheet","errorType":"exception","errorClass":"SpreadsheetException","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Cell/Cell.php","lineNumber":791,"sourceCode":"     */\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());\n    }\n\n    /**\n     * Set Hyperlink.\n     *\n     * @throws SpreadsheetException\n     */\n    public function setHyperlink(?Hyperlink $hyperlink = null): self\n    {\n        if (!isset($this->parent)) {\n            throw new SpreadsheetException('Cannot set hyperlink for cell that is not bound to a worksheet');\n        }\n\n        $this->getWorksheet()","sourceCodeStart":773,"sourceCodeEnd":809,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Cell/Cell.php#L773-L809","documentation":"getHyperlink() needs a bound parent to resolve the worksheet and coordinate, then returns the existing Hyperlink or a newly created default one via Worksheet::getHyperlink(). On a detached Cell the lookup is impossible and the exception is thrown before any hyperlink object is created.","triggerScenarios":"Calling getHyperlink() on a Cell kept after its worksheet was removed or the spreadsheet discarded; deferred consumers of Cell references (queues, iterators, closures) running post-teardown.","commonSituations":"Export enrichers that read link URLs from earlier-captured cells; multi-stage CLI pipelines that free the spreadsheet between stages.","solutions":["Use the worksheet API with a coordinate string: $sheet->getHyperlink('A1')","Guard with $cell->getParent() !== null before calling","Carry coordinates, not Cell objects, across stage boundaries"],"exampleFix":"// before\n$url = $cell->getHyperlink()->getUrl(); // throws when detached\n\n// after\n$url = $sheet->getHyperlink('A1')->getUrl();","handlingStrategy":"validation","validationCode":"if ($cell->getParent() !== null) {\n    $url = $cell->getHyperlink()->getUrl();\n} else {\n    $url = $sheet->getHyperlink($coord)->getUrl();\n}","typeGuard":"function cellIsBoundToWorksheet(Cell $cell): bool\n{\n    return $cell->getParent() !== null && $cell->getParent()->getParent() !== null;\n}","tryCatchPattern":"null","preventionTips":["Extract hyperlink data into plain strings (url, tooltip) before tearing down sheets","Use Worksheet::getHyperlink($coordinate) when you hold the sheet and coordinate","Never let Cell objects cross process/queue boundaries"],"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"}