S7-300 SF Event ID 16#2522: Diagnosing DB Area Length Errors

David Krause15 min read
S7-300SiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

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.

  1. Select PLC > Diagnostics/Setting > Module Information.
  2. Switch to the Stacks tab (in STEP 7 V5.x); in TIA Portal use Online & Diagnostics > Call stack / Stacks.
  3. STEP 7 prompts to "Operating mode: STOP"; confirm.
  4. 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.
  5. 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.
  6. 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.

On the S7-300, the size of the process input / output image is configured under CPU properties > Cycle / Clock Memory > Process Image. The maximum process image size depends on the specific CPU; the CPU 315-2 PN/DP supports up to 2048 bytes. Leaving the default of 128 bytes when the I/O layout spans more addresses is a frequent cause of area length errors on commissioning day.

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

  1. Capture the diagnostic buffer: open PLC > Module Information > Diagnostic Buffer. Note Event ID 16#2522, Info 1..4, and the date / time stamp.
  2. 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.
  3. 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.
  4. 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 from yy onward.
  5. 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.
  6. If the access is indirect: trace the loop counter / index variable. Add a bounds-check (compare index < length − access_width) before the load.
  7. If the access is to the I/O area (PEW / PAW): verify the process image size in the CPU hardware configuration.
  8. If the access uses symbolic names: recompile the entire S7 program (not just the changed block) to refresh the symbol table / address resolution.
  9. Download and restart: place the CPU in STOP, download the corrected blocks, switch to RUN, and observe the diagnostic buffer.
  10. 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.

Masking synchronous errors does not fix the underlying fault. Use masking only when the program is designed to recover from a possibly-failing read, such as checking a present-flag before reading an optional block. Hiding the fault without correcting the access produces silent corruption that may appear much later as wrong process values or as a different event in the buffer.

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:

  1. 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.
  2. 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.
  3. Force / Disable Force test: if force was used during diagnosis, clear all force values and remove the VAT.
  4. 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.
  5. 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.
  6. 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 absolute DBxx.DBD yy accesses. 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.

Back to blog