{"record":{"id":"8350b34837da9d6d","repo":"golang-migrate/migrate","slug":"unmarshaling-json-error-s","errorCode":null,"errorMessage":"unmarshaling json error: %s","messagePattern":"unmarshaling json error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"database/mongodb/mongodb.go","lineNumber":251,"sourceCode":"\tswitch {\n\tcase err == mongo.ErrNoDocuments:\n\t\treturn database.NilVersion, false, nil\n\tcase err != nil:\n\t\treturn 0, false, &database.Error{OrigErr: err, Err: \"failed to get migration version\"}\n\tdefault:\n\t\treturn versionInfo.Version, versionInfo.Dirty, nil\n\t}\n}\n\nfunc (m *Mongo) Run(migration io.Reader) error {\n\tmigr, err := io.ReadAll(migration)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar cmds []bson.D\n\terr = bson.UnmarshalExtJSON(migr, true, &cmds)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unmarshaling json error: %s\", err)\n\t}\n\tif m.config.TransactionMode {\n\t\tif err := m.executeCommandsWithTransaction(context.TODO(), cmds); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif err := m.executeCommands(context.TODO(), cmds); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (m *Mongo) executeCommandsWithTransaction(ctx context.Context, cmds []bson.D) error {\n\terr := m.db.Client().UseSession(ctx, func(sessionContext mongo.SessionContext) error {\n\t\tif err := sessionContext.StartTransaction(); err != nil {\n\t\t\treturn &database.Error{OrigErr: err, Err: \"failed to start transaction\"}\n\t\t}","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/mongodb/mongodb.go#L233-L269","documentation":"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.","triggerScenarios":"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.","commonSituations":"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\": ...}.","solutions":["Fix the JSON syntax reported by the wrapped unmarshal error","Ensure the file is an array of command documents: [{\"insert\": ...}, ...]","Use MongoDB Extended JSON (relaxed or canonical) for dates/ObjectIds: {\"$date\": \"...\"}, {\"$oid\": \"...\"}","Save the file as plain UTF-8 without BOM"],"exampleFix":"// before (migrations/1_create.json)\n{ \"insertOne\": { \"document\": { \"createdAt\": new Date() } } }\n// after\n[ { \"insertOne\": { \"document\": { \"createdAt\": { \"$date\": \"2024-01-01T00:00:00Z\" } } } } ]","handlingStrategy":"validation","validationCode":"var probe []map[string]any\nif err := json.Unmarshal(raw, &probe); err != nil {\n    return fmt.Errorf(\"migration %s is not valid JSON: %w\", path, err)\n}\nif _, ok := raw[0].([]any); !ok {\n    return fmt.Errorf(\"migration %s top level must be an array of commands\", path)\n}","typeGuard":null,"tryCatchPattern":"if err := m.Up(); err != nil {\n    if strings.Contains(err.Error(), \"unmarshaling json error\") {\n        return fmt.Errorf(\"fix Extended JSON in the failed .json migration: %w\", err)\n    }\n    return err\n}","preventionTips":["Validate migration JSON in CI with a strict Extended JSON parser","Use {\"$date\": ...} and {\"$oid\": ...} instead of JS literals like new Date()","Save files as UTF-8 without BOM; lint top-level structure as an array"],"tags":["go","golang-migrate","mongodb","json","parsing","migration-file"],"backgroundTag":"json-parse-error","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}