MOVE_TO_LIT_NOTALLOWED — MOVE_TO_LIT_NOTALLOWED runtime error
MOVE_TO_LIT_NOTALLOWED means ABAP code tried to write a value into a field symbol, dereferenced pointer, or generic work area that currently points to a literal constant instead of a real variable. The runtime refuses the write because literals occupy read-only memory. The fix is in the ABAP code that performed the ASSIGN, not in configuration or master data.
This page covers the MOVE_TO_LIT_NOTALLOWED short dump, which fires when a MOVE, MOVE-CORRESPONDING or CLEAR statement targets a field symbol or reference that has been assigned to a literal rather than a data object. It focuses on the code patterns that actually produce this in production, how to read the ST22 dump to find the offending ASSIGN, and why suppressing the exception is worse than fixing it.
Published 16 Sept 2026· 1,284 words
What the dump means
This dump is raised by the ABAP kernel when a write operation targets memory the runtime has classified as a literal constant. Field symbols and dereferenced data references are generic pointers: at runtime they can be pointed at a variable, a structure field, a table row, or, less obviously, at a literal such as a quoted string, a numeric constant, or a value defined with CONSTANTS. Literals live in read-only program memory. Reading through a field symbol pointed at a literal is fine. Writing to it through MOVE, MOVE-CORRESPONDING, CLEAR, or a plain assignment via the field symbol is not, and the kernel terminates the statement rather than corrupt protected memory. The dump therefore always traces back to an ASSIGN statement, executed earlier in the same call stack, that pointed the field symbol or reference at something that was not a genuine variable.
Root causes that actually produce it
- Literal used as a fallback default: a developer writes ASSIGN 'X' TO <fs> (or ASSIGN a program constant) as the else-branch when a dynamic lookup fails, intending it only as a safe default for reading. Later, shared logic unconditionally does MOVE new_value TO <fs> without checking whether the assignment succeeded against real data, and the fallback branch gets hit in a live transaction.
- Dynamic component resolution falling through: ASSIGN COMPONENT (name) OF STRUCTURE wa TO <fs> is called with a component name built dynamically. When the name does not match any component, sy-subrc is non-zero but the field symbol retains whatever it was pointing at from a previous loop pass, sometimes a literal set earlier in the same routine. The loop body then writes to it without re-checking sy-subrc after each ASSIGN.
- Shared read/write subroutines: a generic form routine or macro is called both to display a value (safe, read-only) and to update it (unsafe). A caller passes a literal by reference or field symbol for the display case, and the same routine is later reused for the update case with the same caller pattern.
- Leftover debug code in enhancements or BAdI implementations: a developer hard-codes ASSIGN 'TEST' TO <fs> while stepping through logic, then forgets to remove it before release. Standard code downstream tries to update the field symbol with a real value and dumps.
- Dynamic field-name construction colliding with a type-pool or program constant: code that builds a field name string for ASSIGN accidentally produces a name that resolves to a constant of the same name rather than the intended structure component, most often in table-control or ALV field-catalog handling.
What to inspect in ST22
- Error category and short text at the top of ST22: confirm it is MOVE_TO_LIT_NOTALLOWED and not a related assignment dump such as GETWA_NOT_ASSIGNED, which points to a different problem.
- Program, include and line number of the failing statement: this is almost always a MOVE, MOVE-CORRESPONDING, or CLEAR statement, and it identifies exactly which field symbol or dereferenced variable is involved.
- Source code extract: read upward from the failing line inside the same routine for the ASSIGN statement that set up that field symbol. It is frequently within a handful of lines, sometimes inside a conditional branch that only triggers for specific input.
- Call stack (active calls and events): check whether the failing include belongs to a customer program, an enhancement, or a BAdI implementation layered onto standard code. This determines who owns the fix.
- Variable or field symbol contents shown lower in the dump, if captured: confirms the actual literal value the pointer resolved to, which often gives away which branch of the code was taken.
- Follow up in SE80 or SE38 on the identified program to trace every ASSIGN against that field symbol name within the routine, and in SE24 or SE37 if the routine sits inside a class method or function module.
Resolution path
If the cause is a literal used as a fallback default, change the code so the write path can never reach that branch: either check sy-subrc after the original ASSIGN and route real writes only to confirmed data objects, or replace the literal default with a properly declared dummy variable that can safely absorb a write. This is a code correction requiring a transport. If the cause is dynamic component resolution falling through, add an explicit check that the resolved component name exists on the structure (via RTTI or a documented list) before the ASSIGN COMPONENT, and re-check sy-subrc on every loop iteration rather than relying on the previous pass. If the cause is leftover debug code in a customer enhancement or BAdI, remove it and release through the normal change request process. If the failing include belongs to unmodified SAP standard code, do not touch the object directly; raise an incident with SAP and, if a production stop is needed immediately, identify and avoid the specific data or variant combination that reaches the literal branch as a temporary workaround, not a fix.
The fix people try first (and why it fails)
The reflex fix is to wrap the failing MOVE in a TRY/CATCH block, or an equivalent classic exception handler, and swallow the error so the program keeps running. This makes the dump disappear from the user's screen but does nothing about the underlying bug: the field symbol still never receives the value it was supposed to hold. The program continues executing with a stale, default, or literal value in a field the business logic assumes was just updated. The resulting data inconsistency surfaces later, often in a different transaction or a downstream report, and is considerably harder to trace back to its origin than the original dump would have been.
Prevention
Flag the pattern ASSIGN literal TO field-symbol during code review and, where available, configure static checks such as Code Inspector or ABAP Test Cockpit to warn on it. Require that any ASSIGN used as a fallback default is followed immediately by an sy-subrc check before the field symbol is reused for a write. Cover every branch of dynamic component resolution logic with unit tests, including the failure branch, so a name mismatch is caught before transport rather than in production.
Whose problem this is
This is an ABAP development defect, not a Basis or functional configuration issue, since it originates in custom code, an enhancement, or a BAdI implementation performing an unsafe ASSIGN. Basis is only involved to help pull the ST22 dump and stack trace. If the failing include is unmodified SAP standard code, escalate to SAP support rather than assign it internally. The handover note should include the program, include and line from ST22, the ASSIGN statement identified above the failing line, and the transaction, variant, or data combination that triggers the branch.
Related SAP objects
Reviewed pages this object connects to in the ERPClimb knowledge graph.
Source: ERPClimb — https://erpclimb.com/sap-abap-dumps/move-to-lit-notallowedERPClimb is an independent platform and is not affiliated with SAP SE. Reference pages are written and reviewed by SAP consultants for learning and troubleshooting.