golang-migrate/migrate · error

unmarshaling json error

Error message

unmarshaling json error: %s

What it means

Raised in Mongo.Run when the migration file's contents fail to parse: bson.UnmarshalExtJSON cannot decode the migration JSON into a list of MongoDB commands ([]bson.D). The error wraps the underlying decoder message. It means the migration file is not valid Extended JSON or its top-level structure is not an array of command documents.

Solutions

  1. Fix the JSON syntax reported by the wrapped unmarshal error
  2. Ensure the file is an array of command documents: [{"insert": ...}, ...]
  3. Use MongoDB Extended JSON (relaxed or canonical) for dates/ObjectIds: {"$date": "..."}, {"$oid": "..."}
  4. Save the file as plain UTF-8 without BOM

Example fix

// before (migrations/1_create.json)
{ "insertOne": { "document": { "createdAt": new Date() } } }
// after
[ { "insertOne": { "document": { "createdAt": { "$date": "2024-01-01T00:00:00Z" } } } } ]
Defensive patterns

Strategy: validation

Validate before calling

var probe []map[string]any
if err := json.Unmarshal(raw, &probe); err != nil {
    return fmt.Errorf("migration %s is not valid JSON: %w", path, err)
}
if _, ok := raw[0].([]any); !ok {
    return fmt.Errorf("migration %s top level must be an array of commands", path)
}

Try / catch

if err := m.Up(); err != nil {
    if strings.Contains(err.Error(), "unmarshaling json error") {
        return fmt.Errorf("fix Extended JSON in the failed .json migration: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: A .json migration containing invalid Extended JSON (e.g. unquoted keys, ISO dates not in {"$date":...} form), a top-level object instead of an array of commands, or BOM/encoding issues in the file.

Common situations: Hand-written migration JSON with JavaScript-style syntax, migrating from JS driver scripts to golang-migrate JSON migrations, editors writing UTF-8 BOM, typo like {createdDate: new Date()} instead of {"$date": ...}.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/8350b34837da9d6d. Report an issue: GitHub.

Appendix: source

Thrown at database/mongodb/mongodb.go:251

	switch {
	case err == mongo.ErrNoDocuments:
		return database.NilVersion, false, nil
	case err != nil:
		return 0, false, &database.Error{OrigErr: err, Err: "failed to get migration version"}
	default:
		return versionInfo.Version, versionInfo.Dirty, nil
	}
}

func (m *Mongo) Run(migration io.Reader) error {
	migr, err := io.ReadAll(migration)
	if err != nil {
		return err
	}
	var cmds []bson.D
	err = bson.UnmarshalExtJSON(migr, true, &cmds)
	if err != nil {
		return fmt.Errorf("unmarshaling json error: %s", err)
	}
	if m.config.TransactionMode {
		if err := m.executeCommandsWithTransaction(context.TODO(), cmds); err != nil {
			return err
		}
	} else {
		if err := m.executeCommands(context.TODO(), cmds); err != nil {
			return err
		}
	}
	return nil
}

func (m *Mongo) executeCommandsWithTransaction(ctx context.Context, cmds []bson.D) error {
	err := m.db.Client().UseSession(ctx, func(sessionContext mongo.SessionContext) error {
		if err := sessionContext.StartTransaction(); err != nil {
			return &database.Error{OrigErr: err, Err: "failed to start transaction"}
		}

View on GitHub (pinned to 01a9643f14)