Dolibarr/dolibarr · error

Bad link. Bad value for parameter modulepart

Error message

Bad link. Bad value for parameter modulepart

What it means

htdocs/document.php serves downloaded documents. On entry it validates GET parameters: if neither modulepart nor the public hashp is provided it calls httponly_accessforbidden() with this message and HTTP 400, because modulepart identifies which module's document directory the file belongs to.

Solutions

  1. Add modulepart to the URL, e.g. document.php?modulepart=invoice&original_file=...
  2. Or use a shared link with hashp if the file is shared publicly
  3. Regenerate the link via Dolibarr's API/templating (dol_buildpath / GETDOCURL helpers) instead of hand-writing it
  4. Check calling code for empty/stripped query parameters

Example fix

// before
echo DOL_URL_ROOT.'/document.php?original_file='.$file;
// after
echo DOL_URL_ROOT.'/document.php?modulepart=facture&original_file='.$file;
Defensive patterns

Strategy: validation

Validate before calling

if (empty($_GET['modulepart']) && empty($_GET['hashp'])) {
  http_response_code(400); exit('modulepart or hashp required');
}

Prevention

When it happens

Trigger: Calling document.php with neither modulepart nor hashp in the query string, e.g. document.php?original_file=...&entity=1 — the security check `empty($modulepart) && empty($hashp)` fires.

Common situations: Hand-built or broken download links; templates generating links that dropped the modulepart parameter; third-party code constructing document URLs without the required parameter; links truncated by encoders.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Dolibarr/dolibarr@598aa4bdad (2026-09-14). Data as JSON: /api/errors/c6ffef9bfc6e46b8. Report an issue: GitHub.

Appendix: source

Thrown at htdocs/document.php:153

 * @var DoliDB $db
 * @var HookManager $hookmanager
 * @var Translate $langs
 * @var User $user
 */
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';

$encoding = '';
$action = GETPOST('action', 'aZ09');
$original_file = GETPOST('file', 'alphanohtml');
$hashp = GETPOST('hashp', 'aZ09');
$modulepart = GETPOST('modulepart', 'alpha');
$urlsource = GETPOST('urlsource', 'alpha');
$entity = ($entity > 0 ? $entity : $conf->entity);

// Security check
if (empty($modulepart) && empty($hashp)) {
	httponly_accessforbidden('Bad link. Bad value for parameter modulepart', 400);
}
if (empty($original_file) && empty($hashp)) {
	httponly_accessforbidden('Bad link. Missing identification to find file (original_file or hashp)', 400);
}
if ($hashp == 'shared') {
	httponly_accessforbidden('Bad link. Bad value for parameter hashp', 400);
}
if ($modulepart == 'fckeditor') {
	$modulepart = 'medias'; // For backward compatibility
}

$socid = 0;
if ($user->socid > 0) {
	$socid = $user->socid;
}

// For some module part, dir may be privates
if (in_array($modulepart, array('facture_paiement', 'unpaid'))) {

View on GitHub (pinned to 598aa4bdad)