hyperledger/fabric · error

object already open, must close object before starting a new

Error message

object already open, must close object before starting a new one

What it means

JSONFileWriter serializes one top-level JSON object field at a time, tracking nesting with an objectOpened flag. OpenObject throws if an object is already open, because JSON cannot nest a bare '{' without a field and the writer enforces open/close discipline.

Source

Thrown at internal/ledgerutil/jsonrw/json_read_write.go:78

func NewJSONFileWriter(filePath string) (*JSONFileWriter, error) {
	f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0o644)
	if err != nil {
		return nil, err
	}

	b := bufio.NewWriter(f)

	return &JSONFileWriter{
		file:    f,
		buffer:  b,
		encoder: json.NewEncoder(b),
	}, nil
}

// Open a json object
func (w *JSONFileWriter) OpenObject() error {
	if w.objectOpened {
		return errors.Errorf("object already open, must close object before starting a new one")
	}

	w.objectOpened = true
	_, err := w.buffer.Write([]byte("{\n"))
	if err != nil {
		return err
	}

	return nil
}

// Close a json object
func (w *JSONFileWriter) CloseObject() error {
	if !w.objectOpened {
		return errors.Errorf("no object open, cannot close object")
	}

	_, err := w.buffer.Write([]byte("}\n"))

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Call CloseObject before each new OpenObject
  2. Move OpenObject out of loops that iterate multiple times
  3. Check error returns of CloseObject so an early return does not leave the object open
  4. Restructure code to open/close per item inside the loop rather than around it

Example fix

// before
w.OpenObject()
for _, v := range items { w.OpenObject() }
// after
for _, v := range items {
    w.OpenObject()
    w.AddField("key", v)
    w.CloseObject()
}
Defensive patterns

Strategy: validation

Validate before calling

type openTracker struct{ objOpen, listOpen bool }

Type guard

func canOpenObject(w *jsonrw.JSONFileWriter, tracked bool) bool { return !tracked }

Try / catch

if err := w.OpenObject(); err != nil {
	return fmt.Errorf("open object: %w", err)
}
defer func() {
	if err := w.CloseObject(); err != nil { log.Error(err) }
}()

Prevention

When it happens

Trigger: Calling OpenObject twice without an intervening CloseObject on the same JSONFileWriter.

Common situations: Loop refactoring bugs where OpenObject is inside a loop instead of outside it, or a forgotten CloseObject on an early-return path.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/2b1c20592a5c3a31. Report an issue: GitHub.