{"record":{"id":"31fd0a580e996585","repo":"iflytek/astron-agent","slug":"insert-app-data-data-must-not-been-nil","errorCode":null,"errorMessage":"insert app data, data must not been nil","messagePattern":"insert app data, data must not been nil","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tenant/internal/dao/app_dao.go","lineNumber":48,"sourceCode":"                   (%s)\n                 VALUES (?,?,?,?,?,?,?,?,?,?,?)`, sqlField)\n\tupdateSql := `UPDATE tb_app SET %s `\n\tselectSql := fmt.Sprintf(`SELECT %s FROM tb_app `, sqlField)\n\tcountSql := `SELECT count(1) from tb_app `\n\n\treturn &AppDao{\n\t\t\tdb:        db,\n\t\t\tinsertSql: insertSql,\n\t\t\tupdateSql: updateSql,\n\t\t\tselectSql: selectSql,\n\t\t\tcountSql:  countSql,\n\t\t},\n\t\tnil\n}\n\nfunc (dao *AppDao) Insert(data *models.App, tx *sql.Tx) (int64, error) {\n\tif data == nil {\n\t\treturn 0, fmt.Errorf(\"insert app data, data must not been nil\")\n\t}\n\tlog.Printf(\"insert app sql is %s\", dao.insertSql)\n\tif tx == nil {\n\t\tresult, err := dao.db.GetMysql().Exec(dao.insertSql,\n\t\t\tdata.AppId, data.AppName, data.DevId, data.ChannelId, data.Source, data.IsDisable, data.Desc, data.IsDelete, data.CreateTime, data.UpdateTime, data.Extend)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"insert app error: %v\", err)\n\t\t\treturn 0, err\n\t\t}\n\t\treturn result.LastInsertId()\n\t}\n\tresult, err := tx.Exec(dao.insertSql,\n\t\tdata.AppId, data.AppName, data.DevId, data.ChannelId, data.Source, data.IsDisable, data.Desc,\n\t\tdata.IsDelete, data.CreateTime, data.UpdateTime, data.Extend)\n\tif err != nil {\n\t\tlog.Printf(\"insert app error: %v\", err)\n\t\treturn 0, err\n\t}","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/tenant/internal/dao/app_dao.go#L30-L66","documentation":"AppDao.Insert refuses to run the INSERT statement when the *models.App argument is nil. The DAO has no way to build column values from a nil row, so it fails fast with this error instead of panicking on a nil pointer dereference inside Exec.","triggerScenarios":"Calling Insert(nil, tx) directly, or indirectly via SaveApp when the constructed/decoded App model is nil (e.g. a JSON unmarshal into *models.App produced nil and was passed through).","commonSituations":"A request body failed to deserialize into *models.App and the handler passed the nil pointer down to SaveApp; a factory function returned nil on an error path that was ignored; code initialized var app *models.App but never assigned it.","solutions":["Check that the *models.App is non-nil before calling SaveApp/Insert and return a validation error to the caller instead.","Fix the upstream construction path so a valid App is always produced or the error is propagated before reaching the DAO.","In the caller (SaveApp), add an early nil check and skip both the app Insert and the auth Insert in the same transaction.","Log the request that produced the nil model to find the deserialization/construction bug."],"exampleFix":"// before\nvar app *models.App\njson.Unmarshal(body, &app) // app stays nil on failure\nid, err := appDao.Insert(app, tx)\n// after\nif app == nil {\n    return 0, fmt.Errorf(\"app payload is required\")\n}\nid, err := appDao.Insert(app, tx)","handlingStrategy":"validation","validationCode":"func validApp(a *models.App) bool { return a != nil && a.AppId != \"\" }","typeGuard":"if app, ok := data.(*models.App); !ok || app == nil {\n    return fmt.Errorf(\"app payload missing\")\n}","tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"data must not been nil\") {\n        return fmt.Errorf(\"invalid request: app payload required: %w\", err)\n    }\n    return err\n}","preventionTips":["Never pass pointers returned from decoders straight to the DAO; check nil after unmarshal.","Have SaveApp construct both App and Auth and verify non-nil before opening the transaction.","Return 400-level validation errors at the handler boundary instead of letting nil reach the DAO layer."],"tags":["go","database","null-check"],"backgroundTag":"null-argument","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}