{"record":{"id":"819364e7ad4f6981","repo":"PHPOffice/PhpSpreadsheet","slug":"cannot-set-hyperlink-for-cell-that-is-not-bound-to","errorCode":null,"errorMessage":"Cannot set hyperlink for cell that is not bound to a worksheet","messagePattern":"Cannot set 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":806,"sourceCode":"    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()\n            ->setHyperlink($this->getCoordinate(), $hyperlink);\n\n        return $this->updateInCollection();\n    }\n\n    /**\n     * Get cell collection.\n     */\n    public function getParent(): ?Cells\n    {\n        return $this->parent;\n    }\n\n    /**\n     * Get parent worksheet.","sourceCodeStart":788,"sourceCodeEnd":824,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Cell/Cell.php#L788-L824","documentation":"setHyperlink() writes the hyperlink to the cell's coordinate on its worksheet, then calls updateInCollection() - both steps need a live parent. With the cell detached there is no worksheet to store the hyperlink on, so the method throws immediately.","triggerScenarios":"Calling setHyperlink($link) on a Cell held after worksheet removal/teardown; applying link changes collected earlier once the target sheet no longer exists.","commonSituations":"Builders that queue hyperlink assignments and flush at the end; processors that delete intermediate sheets before final writes.","solutions":["Write through the worksheet by coordinate: $sheet->setHyperlink('A1', $hyperlink)","Flush hyperlink writes before removing sheets or unsetting the spreadsheet","Guard with $cell->getParent() !== null and drop or requeue detached cells"],"exampleFix":"// before\n$cell->setHyperlink($hyperlink); // throws when detached\n\n// after\n$sheet->setHyperlink('A1', $hyperlink);","handlingStrategy":"validation","validationCode":"if ($cell->getParent() !== null) {\n    $cell->setHyperlink($hyperlink);\n} else {\n    $sheet->setHyperlink($coord, $hyperlink);\n}","typeGuard":"function cellIsBoundToWorksheet(Cell $cell): bool\n{\n    return $cell->getParent() !== null && $cell->getParent()->getParent() !== null;\n}","tryCatchPattern":"null","preventionTips":["Write hyperlinks through Worksheet::setHyperlink($coord, $hyperlink) using coordinate strings","Complete all link writes before sheet removal or spreadsheet teardown","Wrap deferred-write flushes with a liveness check on the target sheet"],"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"}