Skip to content

Gotchas

Each entry starts with the symptom you are likely to see, then shows the root cause and a safe fix. The examples use TCP 192.168.250.100:1025 and the canonical melsec:iq-r profile.

LTN/LSTN/LCN/LZ reads return wrong values

Symptom Root cause Fix
LTN0, LSTN0, LCN0, or LZ0 looks truncated or is rejected. These current-value families are 32-bit values, not normal 16-bit word values. Use :D for unsigned 32-bit or :L for signed 32-bit.
import asyncio

from slmp import SlmpConnectionOptions, open_and_connect, read_named


async def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-r")
    async with await open_and_connect(options) as client:
        values = await read_named(client, ["LTN0:D", "LSTN0:D", "LCN0:L", "LZ0:D"])
        print(values)


asyncio.run(main())

LCS/LCC reads look incorrect

Symptom Root cause Fix
LCS0 or LCC0 does not behave like a normal word read. Long counter state devices are state bits. Reads use direct bit access, and writes are selected through random bit write (0x1402). Use read_named or write_typed with BIT.
import asyncio

from slmp import SlmpConnectionOptions, open_and_connect, read_named, write_typed


async def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-r")
    async with await open_and_connect(options) as client:
        state = await read_named(client, ["LCS0", "LCC0"])
        await write_typed(client, "LCC0", "BIT", True)
        print(state)


asyncio.run(main())

LTS/LTC/LSTS/LSTC write rejected

Symptom Root cause Fix
Direct bit writes to long timer or long retentive timer state devices are rejected. These families need the helper route that selects the supported random bit write behavior. Use write_typed or write_named for the state device.
import asyncio

from slmp import SlmpConnectionOptions, open_and_connect, write_named


async def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-r")
    async with await open_and_connect(options) as client:
        await write_named(client, {"LTS0": True, "LTC0": False})
        await write_named(client, {"LSTS0": True, "LSTC0": False})


asyncio.run(main())

G/HG fails

Symptom Root cause Fix
G100 or HG1000 fails through the high-level typed helpers. Module buffer access is not part of the public high-level typed surface. Use the extended-device API and qualify the module with Ux\G or Ux\HG.
import asyncio

from slmp import AsyncSlmpClient, ExtensionSpec


async def main() -> None:
    async with AsyncSlmpClient("192.168.250.100", 1025, plc_profile="melsec:iq-r") as client:
        values = await client.read_devices_ext("U3\\G100", 4, extension=ExtensionSpec())
        print(values)


asyncio.run(main())

Mixed word and bit write fails

Symptom Root cause Fix
A mixed write containing word devices and bit devices returns a PLC-side error. Some PLCs reject command 0x1406 when word and bit blocks are combined. Split word writes and bit writes into separate helper calls.
import asyncio

from slmp import SlmpConnectionOptions, open_and_connect, write_named


async def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-r")
    async with await open_and_connect(options) as client:
        await write_named(client, {"D100": 42, "D101": 43})
        await write_named(client, {"M100": True})


asyncio.run(main())

DX/DY fails on melsec:iq-f

Symptom Root cause Fix
DX or DY raises an unsupported-device error with melsec:iq-f. The iQ-F profile does not support DX and DY. Use X and Y with melsec:iq-f; their text numbering is octal.
import asyncio

from slmp import SlmpConnectionOptions, open_and_connect, read_named


async def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-f")
    async with await open_and_connect(options) as client:
        values = await read_named(client, ["X100", "Y100"])
        print(values)


asyncio.run(main())

All reads return an end code

Symptom Root cause Fix
Simple reads such as D100 connect but return an SLMP end code. The selected plc_profile does not match the actual PLC family, so the frame type, access mode, or address grammar is wrong. Choose the canonical profile from PROFILES.md in configuration or UI.
import asyncio

from slmp import SlmpConnectionOptions, SlmpError, open_and_connect, read_typed


async def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-r")
    async with await open_and_connect(options) as client:
        try:
            value = await read_typed(client, "D100", "U")
            print(f"D100={value}")
        except SlmpError as exc:
            print(f"PLC rejected the request: 0x{exc.end_code:04X}")


asyncio.run(main())

Missing or non-canonical plc_profile is rejected

Symptom Root cause Fix
Connection setup raises ValueError before any PLC request is sent. plc_profile is required and only canonical profiles are accepted. There is no model-name auto-detection fallback. Set an exact canonical profile such as melsec:iq-r.
from slmp import SlmpConnectionOptions


def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-r")
    print(options.plc_profile)


main()

Concurrent callers crash or interleave responses

Symptom Root cause Fix
Several coroutines share one raw client and responses appear mismatched or fail intermittently. A raw client represents one frame stream and is not a multi-caller scheduler. Use open_and_connect, which returns a queued async client that serializes calls.
import asyncio

from slmp import SlmpConnectionOptions, open_and_connect, read_typed


async def read_one(client: object, address: str) -> int | float:
    return await read_typed(client, address, "U")


async def main() -> None:
    options = SlmpConnectionOptions(host="192.168.250.100", port=1025, plc_profile="melsec:iq-r")
    async with await open_and_connect(options) as client:
        values = await asyncio.gather(
            read_one(client, "D100"),
            read_one(client, "D101"),
        )
        print(values)


asyncio.run(main())

X/Y uses the wrong address

Symptom Root cause Fix
X20 or Y20 points at a different physical address than expected. melsec:iq-f uses octal X/Y text, while other profiles use hexadecimal text. Select the correct canonical profile before parsing string addresses.
from slmp import normalize_address


def main() -> None:
    print(normalize_address("X100", plc_profile="melsec:iq-f"))
    print(normalize_address("X20", plc_profile="melsec:iq-r"))


main()