{"record":{"id":"82d9b91401109e1f","repo":"juicedata/juicefs","slug":"create-table-blob-s","errorCode":null,"errorMessage":"create table blob: %s","messagePattern":"create table blob: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/object/sql.go","lineNumber":205,"sourceCode":"\t}\n\tswitch logger.Level { // make xorm less verbose\n\tcase logrus.TraceLevel:\n\t\tengine.SetLogLevel(log.LOG_DEBUG)\n\tcase logrus.DebugLevel:\n\t\tengine.SetLogLevel(log.LOG_INFO)\n\tcase logrus.InfoLevel, logrus.WarnLevel:\n\t\tengine.SetLogLevel(log.LOG_WARNING)\n\tcase logrus.ErrorLevel:\n\t\tengine.SetLogLevel(log.LOG_ERR)\n\tdefault:\n\t\tengine.SetLogLevel(log.LOG_OFF)\n\t}\n\tif searchPath != \"\" {\n\t\tengine.SetSchema(searchPath)\n\t}\n\tengine.SetTableMapper(names.NewPrefixMapper(engine.GetTableMapper(), \"jfs_\"))\n\tif err := engine.Sync2(new(blob)); err != nil {\n\t\treturn nil, fmt.Errorf(\"create table blob: %s\", err)\n\t}\n\treturn &sqlStore{DefaultObjectStorage{}, engine, addr}, nil\n}\n\nfunc removeScheme(addr string) string {\n\tp := strings.Index(addr, \"://\")\n\tif p > 0 {\n\t\taddr = addr[p+3:]\n\t}\n\treturn addr\n}\n","sourceCodeStart":187,"sourceCodeEnd":217,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/object/sql.go#L187-L217","documentation":"After opening the engine, newSQLStore runs engine.Sync2(new(blob)) to create/migrate the jfs_blob table; failure here is wrapped as 'create table blob'. This means the connection succeeded but DDL failed — typically a permissions or server-side error surfaced by xorm.","triggerScenarios":"engine.Sync2 returns an error: DB user lacks CREATE privilege on the schema/database, the search_path schema doesn't exist (postgres), table exists with incompatible structure, storage full, or the connection dropped mid-DDL.","commonSituations":"Restricted database user with only DML privileges; postgres search_path pointing to a schema that was never created; managed DB (RDS) policies blocking DDL; network interruption between connect and schema sync.","solutions":["Grant the DB user CREATE privilege: GRANT CREATE ON DATABASE jfs TO juicefs; (postgres) or CREATE, ALTER privileges (mysql).","For postgres with search_path, create the schema first: CREATE SCHEMA jfs; AUTHORIZATION juicefs; and GRANT USAGE.","Verify the database accepts DDL (not read-only) and check server logs for the underlying xorm error detail wrapped in the message."],"exampleFix":"// before (fails: schema missing)\nmeta := \"postgres://user:pw@host/db?search_path=jfs\"\n// after (pre-create schema + grants)\n-- psql: CREATE SCHEMA jfs AUTHORIZATION \"user\";\nmeta := \"postgres://user:pw@host/db?search_path=jfs\"","handlingStrategy":"retry","validationCode":"// postgres preflight\nrows, err := db.Query(\"SELECT has_schema_privilege(current_user, $1, 'CREATE')\", schema)\n// or simply try: CREATE TABLE IF NOT EXISTS jfs_blob (...) in a preflight check","typeGuard":null,"tryCatchPattern":"if err := engine.Sync2(new(blob)); err != nil {\n    if pgErr, ok := err.(pgconn.PgError); ok && pgErr.Code == \"42501\" {\n        return fmt.Errorf(\"grant CREATE privilege to the DB user, then retry: %w\", err)\n    }\n    return fmt.Errorf(\"create table blob: %w\", err)\n}","preventionTips":["Grant CREATE/ALTER privileges to the metadata DB user before first mount.","Pre-create the postgres schema referenced by search_path.","Ensure the database is writable (not read-only replica) and reachable."],"tags":["sql","database","ddl","permissions"],"backgroundTag":"database-write-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}