{"record":{"id":"2f27b9f1748d728d","repo":"Dolibarr/dolibarr","slug":"errorfilenotfoundwithsharedlink","errorCode":null,"errorMessage":"ErrorFileNotFoundWithSharedLink","messagePattern":"ErrorFileNotFoundWithSharedLink","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"htdocs/document.php","lineNumber":247,"sourceCode":"\t\t\t}\n\n\t\t\t$entity = $ecmfile->entity;\n\t\t\tif (isModEnabled('multicompany') && !empty($ecmfile->src_object_type) && $ecmfile->src_object_id > 0) {\n\t\t\t\t$object = fetchObjectByElement($ecmfile->src_object_id, $ecmfile->src_object_type);\n\t\t\t\tif (is_object($object) && $object->id > 0) {\n\t\t\t\t\t$entity = $object->entity;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($entity != $conf->entity) {\n\t\t\t\t$conf->entity = $entity;\n\t\t\t\t$conf->setValues($db);\n\t\t\t\t// Multicompany: Here we are switching entity and later we will check the requested object is in this entity but may be that user is not allowed to log/see entity\n\t\t\t\t// but we don't mind, we are using the public hash to get file.\n\t\t\t}\n\t\t} else {\n\t\t\t$langs->load(\"errors\");\n\t\t\thttponly_accessforbidden($langs->trans(\"ErrorFileNotFoundWithSharedLink\"), 403, 1);\n\t\t}\n\t}\n}\n\n// Define attachment (attachment=true to force choice popup 'open'/'save as')\n$attachment = true;\nif (preg_match('/\\.(html|htm)$/i', $original_file)) {\n\t$attachment = false;\n}\nif (isset($_GET[\"attachment\"])) {\n\t$attachment = GETPOST(\"attachment\", 'alpha') ? true : false;\n}\nif (getDolGlobalString('MAIN_DISABLE_FORCE_SAVEAS')) {\n\t$attachment = false;\n}\n\n// Define mime type\n$type = 'application/octet-stream'; // By default","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/Dolibarr/dolibarr/blob/598aa4bdada683d17ca04b1842548821ff0eb6c6/htdocs/document.php#L229-L265","documentation":"When resolving a shared hash, document.php fetches the EcmFiles record by hashp; if the fetch fails (no file with that share hash, possibly after entity/multicompany switch), it loads the 'errors' lang and calls httponly_accessforbidden() with the translated ErrorFileNotFoundWithSharedLink, HTTP 403, meaning the public share link does not correspond to any existing file.","triggerScenarios":"document.php?hashp=<value> where $ecmfile->fetch(0,'','','',$hashp) returns <=0: hash revoked (share removed sets share column empty), hash mistyped/truncated, wrong entity in multicompany, or file deleted.","commonSituations":"Recipients using an old share link after the owner revoked sharing; files deleted or moved in ECM; multicompany entity mismatch between link generation and access; email clients breaking the long hash into lines.","solutions":["Ask the owner to re-share the file and use the fresh link","Verify the file still exists and sharing is enabled in the ECM/documents area","Check the share hash column (llx_ecm_files.share) is not empty and matches the URL","In multicompany setups confirm the correct entity is served for public links"],"exampleFix":"// before (revoked share)\ndocument.php?hashp=revokedhash\n// after: owner re-enables sharing, then use the new hash\ndocument.php?hashp=<newly generated share hash>","handlingStrategy":"fallback","validationCode":"$ecm = new EcmFiles($db);\nif ($ecm->fetch(0,'','','',$hashp) <= 0) {\n  // show 'link expired' page instead of proceeding\n}","typeGuard":null,"tryCatchPattern":"try { if ($ecmfile->fetch(0,'','','',$hashp) <= 0) throw new Exception('not found'); } catch (Exception $e) { render_share_expired_page(); }","preventionTips":["Re-share files after any deletion/move in ECM","In multicompany, generate public links on the correct entity","Communicate link revocations to link recipients","Persist share hashes only for files meant to be public"],"tags":["http-403","share-link","not-found"],"backgroundTag":"file-not-found","analyzedSha":"598aa4bdada683d17ca04b1842548821ff0eb6c6","analyzedAt":"2026-09-14T11:12:15.309Z","contentChangedAt":"2026-09-14T11:12:15.309Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}