Event ID 16#2522: Definition and Classification
Event ID 16#2522 belongs to the class of synchronous programming errors detected by the CPU operating system of a SIMATIC S7-300 or S7-400 during user program execution. When the CPU encounters this fault and OB 121 (Programming Error OB) is not present in load memory, the CPU transitions to STOP, lights the SF (System Fault) LED, and writes a single diagnostic buffer entry containing the Event ID, the point of interruption, and the register / stack context required for root-cause analysis.
The low word of the diagnostic-buffer error filter used by SFC 36 "MSK_FLT" identifies programming errors. Event 16#2522 specifically corresponds to an area length error during a read access to a data block: the program issued a byte, word, or double-word load from a DB address that lies outside the DB's actual length, or that requires more bytes than are still valid inside the DB. The canonical symptom in the field is reading a 32-bit DWORD (REAL or DWORD) from a DB whose declared length stops short of the final byte of that DWORD — for example, fetching a DWORD from byte 28 of a DB that is only 30 bytes long (only bytes 0..29 are valid; bytes 30 and 31 do not exist).
Because the operating system of the S7-300 / S7-400 raises this error synchronously with the offending STEP 7 instruction (as opposed to an asynchronous error like the 16#3500-series diagnostic interrupts), the entire machine state at the fault point — DB register, address register, accumulators, status word, return address — is preserved in the B stack and is retrievable when the CPU is brought online.
Symptoms on the CPU Front Panel
When Event 16#2522 trips without OB 121 present, the CPU exhibits the following panel state:
| LED | State | Meaning |
|---|---|---|
| SF | Red, steady | System fault; diagnostic buffer entry present |
| BF / BF1 / BF2 / BF3 | Off | No bus fault active at this event |
| DC5V | Green | Internal supply OK |
| FRCE | Off | No force active |
| RUN | Off | CPU is in STOP |
| STOP | Yellow, steady | CPU halted due to fault |
| INTF | Off | No interrupt event outstanding |
On a CPU 31x the mode selector must remain in RUN or RUN-P to allow STEP 7 to connect; a STOP-position selector means the user must return it to RUN or RUN-P before online diagnostics are possible.
Decoding the Diagnostic Buffer Entry
Open the project, target the station, and select PLC > Diagnostics/Setting > Diagnostic Buffer in STEP 7 (V5.x) or Online & Diagnostics > Diagnostic buffer in TIA Portal. Scroll to the top entry (most recent event). For Event 16#2522 the buffer entry appears as:
Event 1 of 100: Event ID 16#2522 Event: Area length error when reading (DB) Priority: 6 / 9 / 12 (priority class of the OB in which the error occurred) OB number: 1 (cyclic OB) – indicates the priority class under which the error fired Date/Time: 12.03.2025 14:22:18.345 Info 1: B#16#30 (read access) Info 2: 30 (block number — typically the DB number in which the access occurred) Info 3: 28 (byte offset inside the DB, where the requested access starts) Info 4: 2 (access type code: 1=bit, 2=byte, 3=word, 4=double word)
Decoding the Info fields with respect to the low word of the error filter for programming errors:
| Info field | Value | Decoding |
|---|---|---|
| Info 1 | B#16#30 | Read access error, synchronous programming error |
| Info 2 | Block number | DB number containing the offending address — open this DB |
| Info 3 | 28 | Byte offset of the access inside the block |
| Info 4 | 2 | Access type (1=BIT, 2=BYTE, 3=WORD, 4=DWORD) |
In the field case where Info 4 is 4 (DWORD) and Info 3 is 28, the operating system requested bytes 28, 29, 30, 31 from the data block. If the DB is shorter than 32 bytes — for example, 30 bytes — the operating system cannot satisfy the access and raises 16#2522. The pointer is recorded as DB30.DBD 28 (P#28.0 + width 4).
Reading the Stack When the CPU Is in STOP
Bring STEP 7 online with the target. From the diagnostic buffer entry of Event 16#2522, click "Open Block" (or use the "Go To" button / "Ladder Information" / "Error Location" depending on the editor). STEP 7 opens the block where the access fired and highlights the STEP 7 instruction in red. When the CPU is already in STOP, the more powerful diagnostic is the Stacks tab of the diagnostic buffer entry.
- Select PLC > Diagnostics/Setting > Module Information.
- Switch to the Stacks tab (in STEP 7 V5.x); in TIA Portal use Online & Diagnostics > Call stack / Stacks.
- STEP 7 prompts to "Operating mode: STOP"; confirm.
- Click "B Stack" to display the block stack. The B Stack shows the call hierarchy at the moment the fault occurred: typically OB 1 > FC/FB > the instruction that fired the event.
- Click "I Stack" to display the interrupt stack: the actual DB register, the DI register, the address registers AR1 and AR2, the accumulators ACCU1 and ACCU2, the status word, and the B stack pointer at the time of the fault.
- Click "L Stack" to display the local stack (per-priority local data).
From the I Stack, locate the DB register. The DB register value matches Info 2 of the diagnostic buffer (block number 30 in the example). The DB address pointer (AR2 or the operand of the load instruction) matches the offset. The exact load instruction — for example L DB30.DBD 28 or L "MyDB".REAL_Field in symbolic form — is recoverable from the FC / FB highlighted in the B Stack.
Common Root Causes Seen in the Field
DB length is shorter than the access width requires
The most common cause of Event 16#2522 is reading a 32-bit value from byte 28 of a DB that has not been extended to 32 bytes or more. The actual data layout shows:
| Byte | Field | Type |
|---|---|---|
| 0..1 | Header / status word | WORD |
| 2..27 | Application data | mixed |
| 28..31 | Requested DWORD | DWORD / REAL |
If the DB is 30 bytes long, only bytes 28 and 29 exist; the request for bytes 30 and 31 raises 16#2522. Fix: extend the DB to at least 32 bytes (extend the last field by 2 bytes), recompile, and download.
Indirect addressing overruns the data block
STEP 7 loop constructs that use an indirect DB index — for example OPN DB[MW 0]; L DBD [MD 4] — can compute an offset that walks off the end of the DB. If MD 4 becomes 28 and the loop continues past 28, the next iteration requests bytes 32, 33, 34, 35 and trips the same event. Verify the loop counter and the array bounds in the FC / FB. The stack analysis highlights the FC; review the loop termination condition.
Process image size too small (Scale / analog input case)
When using FC 105 "SCALE" or FB "Scale" with an analog input value read from the process image, the input range must cover the I/O address. If the configured process image size is too small to include the analog input address, the L PEW instruction raises 16#2520 (process image read) or 16#2522 (DB read) depending on whether the operand is taken from PI/PO directly or copied via DB indirection. On a CPU 315-2 PN/DP the default process image size is 128 bytes; increasing the process image size in the hardware configuration under the CPU properties — for example to 256 bytes — resolves the event.
Symbolic access to an undeclared symbol
If a STRUCT or ARRAY field is referenced symbolically and the block was compiled before the new fields were added to the DB, the compiler may generate an access to an offset that no longer exists. Always recompile the user program in full after DB structure changes.
Multi-instance DBs and instance DBs
Multi-instance FBs store their instance data inside the instance DB. Removing an instance variable from the FB and recompiling without re-initializing the instance DB shifts offsets and can cause 16#2522 the first time the instance is called. Re-initialize (PIW) the instance DB after structural changes.
Any-pointer / variant access with stale type information
POINTER, ANY, and VARIANT parameters inherit their target DB number and length at the call site. If a UDT or DB is changed after wiring the call, the ANY pointer still encodes the old length, and the receiving block will trip 16#2522 the first time it dereferences past the old end. Re-generate the ANY from the latest DB / UDT definition.
Step-by-Step Resolution Procedure
- Capture the diagnostic buffer: open PLC > Module Information > Diagnostic Buffer. Note Event ID 16#2522, Info 1..4, and the date / time stamp.
- Open the block: click "Open Block" in STEP 7 V5.x or "Go to" in TIA Portal. The cursor lands on the STEP 7 instruction that fired the fault.
- Inspect the DB size: in the project tree, open the DB referenced by Info 2. Check View > Data View (STEP 7) or the DB declaration (TIA Portal). Confirm whether the requested byte offset + access width exceeds the DB length.
-
Compare access width to declaration: the offending instruction typically is one of
L DBxx.DBD yy,L DBxx.DBW yy,L DBxx.DBB yy. Check the access width and ensure the DB has sufficient bytes fromyyonward. -
Adjust the DB: extend the last data field of the DB so that byte
yy+ access width <= DB length. Recompile and download only the DB. - If the access is indirect: trace the loop counter / index variable. Add a bounds-check (compare index < length − access_width) before the load.
- If the access is to the I/O area (PEW / PAW): verify the process image size in the CPU hardware configuration.
- If the access uses symbolic names: recompile the entire S7 program (not just the changed block) to refresh the symbol table / address resolution.
- Download and restart: place the CPU in STOP, download the corrected blocks, switch to RUN, and observe the diagnostic buffer.
- Verify with a VAT: open a Watch Table with the previously offending address and force / monitor to confirm the value is read without a new buffer entry.
Masking Synchronous Errors with OB 121 and SFC 36 / 37 / 38
For cases where the program expects to read from an address that may or may not be present (for example, a probe read in a fault-tolerant routine, or reading a DB whose length depends on a configuration word), the CPU can be instructed not to enter STOP on Event 16#2522. There are two layers of protection.
Loading OB 121 / OB 122
OB 121 handles programming errors (synchronous errors like 16#2522). OB 122 handles I/O access errors. If OB 121 is downloaded to the CPU, the operating system executes OB 121 instead of going to STOP when Event 16#2522 fires. The local temp variables of OB 121 — OB121_SW_FLT, OB121_FLT_REG, OB121_RESERVED_1, OB121_PRIORITY, OB121_OB_NUMBER, OB121_BLK_NUMBER, OB121_PRG_ADDR, OB121_DATE_TIME — contain the same data as the diagnostic buffer entry, so the OB can log the fault, increment a counter, or simply exit.
Programmatic masking with SFC 36 / SFC 37
To suppress Event 16#2522 (or a subset of synchronous error events) only for specific code regions, use the system function SFC 36 "MSK_FLT" (Mask Synchronous Errors) at the start of the region, and SFC 37 "DMSK_FLT" (Unmask Synchronous Errors) at the end. The call syntax:
CALL "MSK_FLT"
MSK_FLT := B#16#0A // bit 1 (OB 121) and bit 3 (OB 122) cleared — both suppressed
RET_VAL := MW 100
The masking parameter is a bitmask of the synchronous error OBs to suppress; clearing bit 1 masks OB 121 (programming errors) and clearing bit 3 masks OB 122 (I/O access errors). The error status can be queried later with SFC 38 "READ_ERR", which returns the masked error events that have accumulated.
For the full set of synchronous error events and their decoding, see the Siemens reference on Mask Synchronous Error Events (S7-300 / S7-400).
Verification After the Repair
After downloading the corrected DB or program, perform the following checks before returning the controller to production:
- Diagnostic buffer is clear: leave the CPU in RUN for at least 5 minutes with normal I/O exercising. Re-open the diagnostic buffer and confirm no new Event 16#2522 has been logged.
-
Watch table test: add a VAT entry with the previously offending address (
DB30.DBD28) in monitor mode. Verify the value changes as expected and that no SF LED activity occurs. - Force / Disable Force test: if force was used during diagnosis, clear all force values and remove the VAT.
- Online / Offline compare: run PLC > Compare Blocks (offline vs online) to ensure the online and offline project views are consistent. Mismatch after a partial download is a frequent cause of repeat trips.
- Process image boundary: if the fix was process-image size, verify in the hardware configuration that all PEW / PAW references are now within the configured range. A cross-check with the symbol table is recommended.
- Edge-of-range access test: write a one-shot test in OB 100 (warm restart) that reads the last valid byte / word / dword of the DB, and verify the read completes without a buffer entry.
Related Event IDs
| Event ID | Classification | Meaning | First-line response |
|---|---|---|---|
| 16#2520 | Programming error | Area length error reading the process image of inputs | Increase process image size or move operand to direct I/O access (PEW) |
| 16#2521 | Programming error | Area length error reading an instance DB / multi-instance | Verify instance DB length vs FB declaration |
| 16#2522 | Programming error | Area length error reading a data block | Verify DB length vs requested offset + width |
| 16#2523 | Programming error | Area length error writing a data block | Same as 16#2522, but for T DBxx.DBD |
| 16#2524 | Programming error | Area length error reading a bit | DB length or bit offset exceeds DB length × 8 |
| 16#2525 | Programming error | Area length error writing a bit | Same as 16#2524 for write access |
| 16#2526 | Programming error | DB not loaded | DB number wrong or DB not downloaded |
| 16#2527 | Programming error | DB protection error / wrong password | Check DB know-how protection and password |
| 16#2528 | Programming error | Nesting depth exceeded in OB | Reduce block-call nesting or increase OB priority stack |
| 16#2529 | Programming error | Nesting depth exceeded in FB | Check recursive FB calls |
| 16#253A | Programming error | Area length error on process image write | Same as 16#2520 for writes (T PAW) |
| 16#253C | Programming error | Pointer error | Inspect area-internal pointer arithmetic |
| 16#253D | Programming error | Substitute missing | No error OB present for a detected fault class |
| 16#253E | Programming error | Substitute missing in OB | Same as 16#253D inside OB |
| 16#253F | Programming error | System error | CPU firmware bug; check firmware update |
Events 16#2520 and 16#253A specifically target the process image. Events 16#2521..16#2525 target DBs. Events 16#2526..16#2529 target FB / FC / DB availability and nesting. Differentiate by reading Info 1 (access direction), Info 2 (block number), Info 3 (offset), and Info 4 (access type).
Preventive Measures for Commissioning
The 16#2522 family of errors is fully preventable with disciplined commissioning practice:
- Reserve access headroom: declare DBs with at least 8 bytes of unused length after the last symbolic field. This avoids DB-length-sensitive bugs when new fields are appended.
-
Avoid hard-coded DBD offsets: use symbolic names (
"MyDB".MyValue) instead of absoluteDBxx.DBD yyaccesses. Compiler-driven offset regeneration eliminates hand-tracking errors. - Bound-check indirect addressing: any loop or pointer arithmetic that walks a DB must check the index + access width against the configured DB length before the load.
- Set the process image explicitly: configure a process image size that matches the largest I/O address used. Avoid leaving the default and discovering it too late.
- Use OB 121 as a fallback, not as a mask: load OB 121 to log and continue, but the program logic should not rely on it for correctness.
- Full project compile after every change: a partial compile may leave stale symbolic-to-absolute mappings. Use Program > Compile All (Reset / Rebuild) in STEP 7 or TIA Portal after structural changes.
- Test with maximum-offset probe: at site acceptance, run a routine that reads the last valid byte / word / dword of every configured DB and writes it back. A successful read confirms the length matches the access pattern.
- Document DB layouts in a revision-controlled sheet: a one-page sheet per DB listing byte offsets and access widths short-circuits 80% of future 16#2522 incidents.
FAQ
What does Event ID 16#2522 mean on an S7-300 CPU?
Event ID 16#2522 is a synchronous programming error raised by the S7-300 / S7-400 CPU when the user program issues a read access (load instruction) to a data block at an offset that, combined with the access width, would exceed the DB's declared length. Typical example: L DB30.DBD 28 on a 30-byte DB.
Why does my CPU go to STOP instead of just logging the error?
The CPU goes to STOP on Event 16#2522 only when OB 121 (the programming-error OB) is not present in load memory. To prevent the STOP, download an OB 121 — even an empty one — to the CPU. The CPU will then execute OB 121 on the fault and continue running.
How do I find which instruction raised 16#2522?
Open the diagnostic buffer entry of 16#2522 in STEP 7 (PLC > Module Information > Diagnostic Buffer) and click "Open Block" — STEP 7 jumps to the offending instruction and highlights it in red. If the CPU is in STOP, switch to the Stacks tab and read the B Stack / I Stack for the call hierarchy and register state at the fault.
Can I suppress Event 16#2522 programmatically without changing the DB?
Yes, temporarily: call SFC 36 "MSK_FLT" with the OB 121 bit cleared in the parameter MSK_FLT to mask programming errors around a specific code region, and call SFC 37 "DMSK_FLT" to unmask afterward. The masked errors accumulate in the event status register and can be read with SFC 38 "READ_ERR".
Does the process image size fix apply only to analog inputs?
Any operand addressed as PEW / PAW (process image input / output word) is subject to the configured process image size. If the address lies outside the configured image, the CPU raises an area length error (typically 16#2520 for reads, 16#253A for writes). Increase the size under CPU properties > Process Image in the hardware configuration.