[Bug]: Subcontracting: SetIsSubcontracting calls CurrPage.Update() with SaveRecord = true from OnAfterGetCurrRecord, aborting the Transfer Order page
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 76/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Área
- frontend
Línea de trabajo
Inspecciona src/Apps/W1/Subcontracting/App/src/Transfer/SubcTransOrderSub.PageExt.al en SetIsSubcontracting y su llamador en SubcTransferOrder.PageExt.al. Confirma que la actualización de la página no guarda el registro y, a continuación, vuelve a ejecutar 00_Repro_Setup.yml y 01_Repro_R1_Release.yml en los entornos de Business Central indicados; Release y Create Whse. Shipment deberían completarse sin ninguno de los dos errores de Transfer Line.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Describe the issue
On the Transfer Order page, Subc. Trans. Order Sub. (PageExtension 20529) forces a saving page update from inside a record-fetch trigger. That aborts the page during the normal transfer document flow.
The statement
internal procedure SetIsSubcontracting(IsSubcontractingRelated: Boolean)
begin
HasSubcontractingContext := IsSubcontractingRelated;
CurrPage.Update(); // SaveRecord defaults to true
end;
CurrPage.Update() with no argument is CurrPage.Update(true), so it saves the record. The procedure only assigns a visibility Boolean, so there is nothing that needs saving.
The caller
trigger OnAfterGetCurrRecord()
begin
#if not CLEAN29
if not SubcontractingEnabled then
exit;
#endif
ShowSubcontractingFactBox := SubcTransferManagement.IsSubcontractingTransferDocument(Rec);
CurrPage.TransferLines.Page.SetIsSubcontracting(ShowSubcontractingFactBox);
end;
OnAfterGetCurrRecord fires on every current-record refresh, including moments when the subform line is not in a clean committed state. The forced save then fails in one of two ways:
- Brand-new subform line,
Line No.not yet assigned. The platform resolves the save as a rename, which reachesTable 5741 "Transfer Line".OnRename- an unconditionalError. A Transfer Line can never be renamed, so the abort is guaranteed. - Existing line whose page copy is older than the stored record. Optimistic concurrency rejects the write.
Observed errors
Business Central 29.0.54011, India (IN) localisation, clean sandbox, no third-party extensions installed.
Variant A - uncommitted line:
You cannot rename a Transfer Line
Microsoft.Dynamics.Nav.Runtime.FormAbortException: Page Transfer Order has to close
Variant B - committed line, stale page copy:
The changes to the Transfer Line record cannot be saved because some information on the
page is not up-to-date. Close the page, reopen it, and try again.
Identification fields and values: Document No.='1006', Line No.='10000'
Call stack
Copied from the client's Share details pane. Identical for both variants, two frames, both in this extension.
"Subc. Trans. Order Sub."(PageExtension 20529).SetIsSubcontracting line 3
- Subcontracting by Microsoft version 29.0.54011.54955
"Subc. Transfer Order"(PageExtension 20526).OnAfterGetCurrRecord(Trigger) line 8
- Subcontracting by Microsoft version 29.0.54011.54955
SetIsSubcontracting line 3 is the CurrPage.Update() statement. The trigger's reported line 8 does not line up with line 8 of the source above because the #if not CLEAN29 directives are compiled out of the shipped artifact; line 8 in the compiled object is the SetIsSubcontracting call.
IN localisation, no third-party extensions. Release itself succeeded here and the failure landed on the next action, which is why we say the trigger, not the action, is the cause.
One more observation
The subform's own OnAfterGetCurrRecord guards itself against repeated work:
local procedure SetSubcontractingVisibility()
begin
if Rec."Document No." = TransferHeader."No." then
exit;
The call arriving from the parent page has no equivalent guard, so SetIsSubcontracting and its forced save run on every refresh.
Expected behavior
Adding a line to a Transfer Order and then invoking Release, or Create Whse. Shipment, should complete normally: the order is released and the warehouse shipment is created. No extension should force a saving page update from a record-fetch trigger.
SetIsSubcontracting assigns a visibility Boolean and nothing else, so it should refresh the page without writing the record:
internal procedure SetIsSubcontracting(IsSubcontractingRelated: Boolean)
begin
HasSubcontractingContext := IsSubcontractingRelated;
- CurrPage.Update();
+ CurrPage.Update(false);
end;
CurrPage.Update(false) redraws the page and re-evaluates the Visible properties bound to HasSubcontractingContext, which is all this procedure needs. It cannot trigger a write, so neither failure mode can occur.
Steps to reproduce
About two minutes. No item tracking, no extensions, no special configuration.
- Provision a Business Central 29.0.54011 sandbox on the IN (India) localisation, standard CRONUS, with no third-party apps installed.
- Open Transfer Orders and choose New.
- Set Transfer-from Code, Transfer-to Code and In-Transit Code. On CRONUS IN:
EAST,WEST,OUT. LOG. - On the lines subform, enter an Item No. (for example
1896-S) and Quantity10. - Without changing focus after typing the quantity, click Release.
- Then click Create Whse. Shipment.
The error appears at step 5 or step 6. Which one you get depends only on whether the subform line had already been committed when the trigger fired; both come from the same code path and produce the same call stack.
Tested on artifacts 29.0.54011.54884, .54955, .55000 and .55007. Present on IN in all of them, including the newest.
Additional context
Why it surfaces only on IN
We ran the same automated suite of 1435 tests twice from one pipeline, minutes apart, against the same artifact sandbox/29.0.54011.55007, with the localisation as the only difference:
| Localisation | Result |
|---|---|
| W1 / base | 1435 tests, 0 failures |
| IN | 1435 tests, 6 failures - every one with the error and call stack above |
Same split on artifact .54884. We also reproduced it by hand in the web client on IN and confirmed it passing on W1, using byte-identical BC Page Scripting recordings that create every object they touch, which rules out demo data and configuration.
W1 / base. The same two recordings, byte for byte, complete without errors.
The Subcontracting app is installed on both localisations - on W1 it is listed in Extension Management as published Global and installed - so the presence of the app is not the discriminator.
Our reading of the gate
The likely gate is the #if not CLEAN29 guard in PageExtension 20526:
#if not CLEAN29
if not SubcontractingEnabled then
exit;
#endif
SubcontractingEnabled comes from Subc. Feature Flag Handler.IsSubcontractingEnabled(), which returns not ManufacturingSetup."Legacy Subcontracting". So on a company where Legacy Subcontracting is still on, the trigger exits at the guard and the bug is invisible; where it is off, the forced save runs. That would make this a demo-data difference rather than localised code.
We have not confirmed the flag's value on each localisation, so please treat that as our reading rather than as established.
It also means the guard disappears entirely once CLEAN29 is defined, at which point the forced save runs unconditionally on every localisation.
Attached: the Page Scripting recordings
I have attached the two BC Page Scripting recordings we used -
00_Repro_Setup.yml
01_Repro_R1_Release.yml
| File | What it does |
|---|---|
00_Repro_Setup.yml |
Creates everything the repro needs, from base functionality only: an item tracking code, an item, and three locations (from, to, and in-transit). Run once per container. |
01_Repro_R1_Release.yml |
Creates the transfer order and its line, invokes Release and then Create Whse. Shipment, and validates the resulting warehouse shipment line. |
Both use base objects only and create every object they touch, so the same two files run unchanged on any localisation with no demo-data dependency. Import them through the Page Scripting pane in the web client (Preview feature) and replay.
On IN the second script stops at Release or at Create Whse. Shipment. On W1 it runs to the end with every validation passing. That is the comparison shown in the two screenshots above.
Impact
Releasing a transfer order and creating its warehouse shipment is core inventory functionality, and this reproduces with a stock item, stock locations, no item tracking and no extensions, so it is not configuration-dependent. It also breaks any partner or ISV extension that drives the Transfer Order page on an affected company.
We have the two BC Page Scripting .yml recordings that reproduce it in a single run, plus the full client error details including session and activity IDs. Happy to attach any of it on request.
I will provide a fix for a bug
- I will provide a fix for a bug
- Lenguaje dominante
- AL
- Estrellas
- 683
- Forks
- 459
- Merge medio
- 2 d 19 h
- PR fusionados (30 d)
- 521
Preparar el entorno
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de microsoft/BCApps
-
Team: SCM
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
microsoft/BCApps#12154 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Approved extensibility-enhancement Ownership: Needs Review Team: Integrations Team: Other
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
microsoft/BCApps#12144 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
Approved ext-ready-to-implement request-for-external Team: Finance
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
microsoft/BCApps#12069 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Approved request-for-external Team: SCM
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
microsoft/BCApps#12033 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Approved request-for-external Team: SCM
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
microsoft/BCApps#12032 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de microsoft/BCApps
Issues similares
-
Area/Workflow Priority/Blocker Type/Bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
wso2/product-integrator#2622 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
-
P3
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
SocialGouv/code-du-travail-numerique#7532 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Inter-Actief/alexia#149 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
MemberJunction/MJ#4947 · 1 comentario ·
Los mantenedores suelen responder en 1 día