siyuan-note/siyuan · error · ErrInvalidAttributeViewID

invalid attribute view id

Error message

invalid attribute view id

What it means

Sentinel error av.ErrInvalidAttributeViewID (kernel/av/av.go:1294). ParseAttributeView (av.go:739), ParseAttributeViewInBox (av.go:758), SaveAttributeView (av.go:892) and the encrypted-box hook (encrypted_hook.go:206) reject any avID that fails lute's ast.IsNodeIDPattern — the fixed-format node-ID pattern used for all SiYuan block/av IDs. Because the ID becomes a filename under storage/av/, this doubles as a path-traversal guard: '../outside', 'nested/outside' and similar are rejected (covered by kernel/av/path_test.go).

Solutions

  1. Use IDs produced by the system: av.NewAttributeView() / ast.NewNodeID(), or an avID copied from an existing database block's custom-avs attribute
  2. Validate the ID shape before calling (fixed-length node-ID pattern, no slashes/dots)
  3. Fetch the correct ID via the av APIs rather than guessing
  4. If you maintain external tooling, keep the avID mapping table so IDs are never reconstructed from names

Example fix

// before
avView, err := av.ParseAttributeView("my-database")

// after
avID := ast.NewNodeID() // or an id obtained from an existing av
avView, err := av.ParseAttributeView(avID)
Defensive patterns

Strategy: type-guard

Validate before calling

// Go callers: validate before calling any av API
if !ast.IsNodeIDPattern(avID) {
    return fmt.Errorf("rejecting malformed attribute view id %q", avID)
}
_, err := av.ParseAttributeView(avID)

Type guard

func isValidAvID(id string) bool {
    return ast.IsNodeIDPattern(id) // same pattern the kernel enforces; rejects paths and names
}

Try / catch

if _, err := av.ParseAttributeView(avID); err != nil {
    if errors.Is(err, av.ErrInvalidAttributeViewID) {
        // the id is malformed or contains path characters: do not retry, reject the input
    }
}

Prevention

When it happens

Trigger: Passing a human-chosen name ('mydb'), a file path ('../outside'), an empty string, or any non-pattern string as avID to an /api/av/* endpoint or to the kernel Go functions; plugins feeding user input straight into ParseAttributeView.

Common situations: Plugin authors inventing their own ID scheme instead of using av.NewAttributeView(); API scripts copying an av 'name' where the ID belongs; IDs mangled by URL truncation or encoding.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/efe0da854916af88. Report an issue: GitHub.

Appendix: source

Thrown at kernel/av/av.go:1294

	av := filepath.Join(util.DataDir, "storage", "av")
	ret = filepath.Join(av, avID+".json")
	if !gulu.File.IsDir(av) {
		if err := os.MkdirAll(av, 0755); err != nil {
			logging.LogErrorf("create attribute view dir failed: %s", err)
			return
		}
	}
	return
}

func GetAttributeViewI18n(key string) string {
	return util.AttrViewLangs[util.Lang][key].(string)
}

var (
	ErrAttributeViewNotFound  = errors.New("attribute view not found")
	ErrInvalidAttributeViewID = errors.New("invalid attribute view id")
	ErrInvalidBoxID           = errors.New("invalid box id")
	ErrViewNotFound           = errors.New("view not found")
	ErrKeyNotFound            = errors.New("key not found")
	ErrItemNotFound           = errors.New("item not found")
	ErrWrongLayoutType        = errors.New("wrong layout type")
	ErrInvalidColumnAlign     = errors.New("invalid column align")
	ErrSpecTooNew             = errors.New("attribute view spec is too new")
	ErrFilterTooDeep          = errors.New("filter nesting depth exceeds the maximum allowed")
)

const (
	NodeAttrNameAvs        = "custom-avs"                 // 用于标记块所属的属性视图,逗号分隔 av id
	NodeAttrView           = "custom-sy-av-view"          // 用于标记块所属的属性视图视图 view id Database block support specified view https://github.com/siyuan-note/siyuan/issues/10443
	NodeAttrVisibleViewIDs = "custom-sy-av-visible-views" // 用于标记数据库块显示的视图 ID,逗号分隔
	NodeAttrViewStaticText = "custom-sy-av-s-text"        // 用于标记块所属的属性视图静态文本 Database-bound block primary key supports setting static anchor text https://github.com/siyuan-note/siyuan/issues/10049

	NodeAttrViewNames = "av-names" // 用于临时标记块所属的属性视图名称,空格分隔
)

View on GitHub (pinned to afa823b6b4)