Skip to content

Loading own house crashes ZZ client on 9.3.2 (empty furniture fallback) #192

Description

@Houmgaor

Reported by

A user on Erupe 9.3.2, ZZ client.

"trying to go to my House crashes the game 🤔"

Symptom

The player attempts to enter their own house. Server processes MSG_MHF_LOAD_HOUSE (0x00AA), ACKs, and ~1.3s later the client crashes (TCP forcibly closed by remote).

Server log

22:29:24.682  Tifa → Server  MSG_MHF_LOAD_HOUSE
              data: 00 aa 01 fd 00 05 00 00 00 01 09 01 00 00 01 00 00 10
22:29:24.682  Server → Tifa  MSG_SYS_ACK (latency 503µs)
              data: 00 12 01 fd 00 05 01 00 00 14 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00
22:29:25.957  WARN  Connection error, exiting recv loop
              error: ... An existing connection was forcibly closed by the remote host

Diagnosis

Decoded request: CharID=1 (self), Destination=9 (own house).

Response payload after the ACK header: 20 zero bytes. That comes from handlers_house.go:

if houseFurniture == nil {
    houseFurniture = make([]byte, 20)   // empty fallback
}
...
case 9: // Own house
    bf.WriteBytes(houseFurniture)        // sends 20 zero bytes

GetHouseContents returns user_binary.house_furniture (repo_house.go:78). When NULL, the 20-zero fallback fires — and the ZZ client cannot parse it, so it crashes.

Possibly related: #92

#92 (closed 2026-03-18) fixed corruption of the sibling house_tier column in user_binary on the save path (client sometimes wrote 0xFF..., wiping the theme).

This bug affects the adjacent house_furniture column on the load path. Both columns are read together by GetHouseContents. Worth checking whether the affected character's house_furniture is NULL (never initialized) or non-NULL but malformed:

SELECT length(house_furniture) FROM user_binary WHERE id = 1;

If empty saves are reaching the column, the same detect-and-restore pattern from #92 may need to be extended to house_furniture (and possibly house_data, bookshelf, gallery, tore, garden).

Suggested fixes

  • Defensive (short-term): return doAckSimpleFail instead of 20 zero bytes when houseFurniture is nil for Destination=9. A failed ACK is recoverable; a client crash is not.
  • Correct fix: capture a real LOAD_HOUSE (Destination=9) response from a brand-new ZZ character to determine the correct empty-state encoding, and either initialize a default row on character creation or emit that exact shape from the fallback.

Repro

  • Server: 9.3.2 · Client: ZZ
  • Log in, attempt to enter own house → client crashes ~1s after the LOAD_HOUSE ACK.

Code paths

  • server/channelserver/handlers_house.go (handleMsgMhfLoadHouse, ~L119–214)
  • server/channelserver/repo_house.go (GetHouseContents, ~L76)
  • server/channelserver/handlers_data.go (House Theme Disappears when login back to the game. #92 fix, ~L93–105)
  • network/mhfpacket/msg_mhf_load_house.go

Severity

Critical — full client crash on a routine action, no in-game workaround.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcriticalSoftlocks, data loss, crashesgame-systemGameplay features (quests, guilds, gacha, housing)protocolPacket parsing, network protocol issues

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions