Repository: SplashSync/Dolibarr
Module version: 2.23.3
Dolibarr: 23.0.0
Related: the ECM updateFilesPath() issue has the same origin — the raw reference is used where Dolibarr stores a sanitised one.
Summary
Dolibarr sanitises a product reference on creation (dol_sanitizeFileName(dol_string_nospecial(...))),
so a reference containing / is stored with _. Splash keeps using the raw reference: it cannot
find the product it just created, tries to create it again on the next sync, and Dolibarr refuses.
The product is permanently unlinked and every sync raises the same error.
Error
Splash\Local\Objects\Product::createSimpleProduct() => Error : Un produit avec la référence existe déjà.
Unable to create new Product.
What actually happens
Source SKU (WooCommerce): SAM-DIRT2/3-LAC-1200-25-N
raw reference : SAM-DIRT2/3-LAC-1200-25-N
dol_string_nospecial() -> SAM-DIRT2_3-LAC-1200-25-N
dol_sanitizeFileName() -> SAM-DIRT2_3-LAC-1200-25-N
Dolibarr therefore stores SAM-DIRT2_3-LAC-1200-25-N (product id 692, created by the very first
sync). On the next sync Splash looks up SAM-DIRT2/3-LAC-1200-25-N, finds nothing, calls
createSimpleProduct() with the raw reference, and Product::create() — which sanitises again —
hits the existing row and returns ErrorProductAlreadyExists.
The loop is permanent: the product exists, is correct, and can never be linked or updated.
Second symptom, same cause
The raw reference is also used to build the ECM path, producing entries such as:
filepath = 'produit/SAM-DIRT2/3-LAC-1200-25-N'
The / inside the reference makes it look like a nested folder, and these rows can never match a
product folder again. On our install this left 8 permanently orphaned ECM entries — one per
slash-bearing SKU.
Steps to reproduce
- Give a WooCommerce product a SKU containing
/ (or any character dol_string_nospecial() maps).
- Sync: the Dolibarr product is created, with a sanitised reference.
- Sync again:
Unable to create new Product / Un produit avec la référence existe déjà, forever.
Suggested fix
Sanitise before lookup and before creation, so Splash and Dolibarr agree on the stored value:
// same transformation Dolibarr applies in Product::create()
$dolRef = dol_sanitizeFileName(dol_string_nospecial(trim($ref)));
- use
$dolRef when searching for an existing product before creating one;
- use
$dolRef when building the ECM path in updateFilesPath();
- after
Product::create(), if $product->ref !== $ref, log a warning naming both values, so the
divergence is visible instead of silent.
Refusing such references outright would also be defensible, but silently creating a product that can
never be found again is the worst of the three options.
Diagnosability
The current message names neither the reference nor the conflicting product. Adding that context
turns an opaque failure into a self-explanatory one — this is what we patched locally to identify
the problem:
Unable to create new Product [ref: SAM-DIRT2/3-LAC-1200-25-N / label: Cours 2025/2026 Lacroix-Falgarde]
- reference already used by product id 692 (Dolibarr ref: SAM-DIRT2_3-LAC-1200-25-N / ...)
The / → _ transformation is then visible directly in the error, and the cause is obvious at a
glance. See the companion issue on attribute error context — same class of improvement.
Repository: SplashSync/Dolibarr
Module version: 2.23.3
Dolibarr: 23.0.0
Related: the ECM
updateFilesPath()issue has the same origin — the raw reference is used where Dolibarr stores a sanitised one.Summary
Dolibarr sanitises a product reference on creation (
dol_sanitizeFileName(dol_string_nospecial(...))),so a reference containing
/is stored with_. Splash keeps using the raw reference: it cannotfind the product it just created, tries to create it again on the next sync, and Dolibarr refuses.
The product is permanently unlinked and every sync raises the same error.
Error
What actually happens
Source SKU (WooCommerce):
SAM-DIRT2/3-LAC-1200-25-NDolibarr therefore stores
SAM-DIRT2_3-LAC-1200-25-N(product id 692, created by the very firstsync). On the next sync Splash looks up
SAM-DIRT2/3-LAC-1200-25-N, finds nothing, callscreateSimpleProduct()with the raw reference, andProduct::create()— which sanitises again —hits the existing row and returns
ErrorProductAlreadyExists.The loop is permanent: the product exists, is correct, and can never be linked or updated.
Second symptom, same cause
The raw reference is also used to build the ECM path, producing entries such as:
The
/inside the reference makes it look like a nested folder, and these rows can never match aproduct folder again. On our install this left 8 permanently orphaned ECM entries — one per
slash-bearing SKU.
Steps to reproduce
/(or any characterdol_string_nospecial()maps).Unable to create new Product/Un produit avec la référence existe déjà, forever.Suggested fix
Sanitise before lookup and before creation, so Splash and Dolibarr agree on the stored value:
$dolRefwhen searching for an existing product before creating one;$dolRefwhen building the ECM path inupdateFilesPath();Product::create(), if$product->ref !== $ref, log a warning naming both values, so thedivergence is visible instead of silent.
Refusing such references outright would also be defensible, but silently creating a product that can
never be found again is the worst of the three options.
Diagnosability
The current message names neither the reference nor the conflicting product. Adding that context
turns an opaque failure into a self-explanatory one — this is what we patched locally to identify
the problem:
The
/→_transformation is then visible directly in the error, and the cause is obvious at aglance. See the companion issue on attribute error context — same class of improvement.