wavetermdev/waveterm · error

too many iterations looking for tab in block parents

Error message

too many iterations looking for tab in block parents

What it means

DBFindTabForBlockId walks the parent chain of blocks (block -> parent oref -> ...) up to 5 hops to find the enclosing tab. If it has not reached a tab after 5 iterations it gives up with this error, protecting against cycles or unexpectedly deep block nesting in the layout tree.

Source

Thrown at pkg/wstore/wstore_dbops.go:369

	if err != nil {
		return err
	}
	return WithTx(ctx, func(tx *TxWrap) error {
		table := waveObjTableName(val)
		waveobj.SetVersion(val, 1)
		query := fmt.Sprintf("INSERT INTO %s (oid, version, data) VALUES (?, ?, ?)", table)
		tx.Exec(query, oid, 1, jsonData)
		waveobj.ContextAddUpdate(ctx, waveobj.WaveObjUpdate{UpdateType: waveobj.UpdateType_Update, OType: val.GetOType(), OID: oid, Obj: val})
		return nil
	})
}

func DBFindTabForBlockId(ctx context.Context, blockId string) (string, error) {
	return WithTxRtn(ctx, func(tx *TxWrap) (string, error) {
		iterNum := 1
		for {
			if iterNum > 5 {
				return "", fmt.Errorf("too many iterations looking for tab in block parents")
			}
			query := `
			SELECT json_extract(b.data, '$.parentoref') AS parentoref
			FROM db_block b
			WHERE b.oid = ?;`
			parentORef := tx.GetString(query, blockId)
			oref, err := waveobj.ParseORef(parentORef)
			if err != nil {
				return "", fmt.Errorf("bad block parent oref: %v", err)
			}
			if oref.OType == "tab" {
				return oref.OID, nil
			}
			if oref.OType == "block" {
				blockId = oref.OID
				iterNum++
				continue
			}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Inspect the block's parent chain (db_block.parentoref values) for cycles or excessive depth and repair the layout
  2. Re-create or flatten the offending nested layout so the tab is within 5 levels
  3. Verify blockId is valid and the chain terminates at a tab, not another container type
Defensive patterns

Strategy: try-catch

Try / catch

tabId, err := wstore.DBFindTabForBlockId(ctx, blockId)
if err != nil {
	if strings.Contains(err.Error(), "too many iterations") {
		// fall back to workspace-level lookup or rebuild layout
	}
	return err
}

Prevention

When it happens

Trigger: Passing a blockId whose parent chain is longer than 5 block levels, a cyclic parentoref layout, or a corrupted block row whose parent points back into the same block tree indefinitely.

Common situations: Deeply nested split/pane layouts created programmatically; corrupted waveai/state DB rows with self-referential parent orefs; calling the function with a root-level block whose chain never terminates in a tab.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/9607711728b314eb. Report an issue: GitHub.