siyuan-note/siyuan · error
at least one asset path or mapping is required
Error message
at least one asset path or mapping is required
What it means
newAssetRelinkPlan requires at least one mapping (an asset path to find or an old/new pair to relink). An empty mappings slice cannot form a plan, so the constructor fails immediately with this error before any scanning.
Solutions
- Check the input list length before calling and return a client-side validation message for empty input
- Populate at least one mapping with a non-empty OldPath
- If filtering may remove all entries, skip the API call entirely when the filtered list is empty
Example fix
// before
result, err := model.RelinkAssets(ctx, filtered, dryRun) // filtered may be empty
// after
if len(filtered) == 0 {
return nil, errors.New("no asset mappings to relink")
}
result, err := model.RelinkAssets(ctx, filtered, dryRun) Defensive patterns
Strategy: validation
Validate before calling
if len(mappings) == 0 { return errors.New("provide at least one asset mapping") } Type guard
if mappings == nil || len(mappings) == 0 { return false } Prevention
- Validate request payload emptiness at the API layer before invoking the model
- Skip the call entirely when a filtered list becomes empty
- Write tests covering empty-input cases for batch APIs
When it happens
Trigger: Calling FindAssetReferencesBatch with an empty paths slice, RelinkAssets with an empty mappings slice, or an API handler that drops all entries after filtering, reaching newAssetRelinkPlan with len(mappings)==0.
Common situations: UI sends no selected assets; a script filters mappings and passes an empty array; API integration bug that never populates the paths parameter.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- AI editor input is empty
- all asset mappings failed
- asset data is empty
- assetPath is not an image referenced by the document
- assetPath is required for analyze
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/1595a8cd0402a333.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/asset_relink_batch.go:70
func FindAssetReferencesBatch(ctx context.Context, paths []string) (apicontract.AssetReferencesData, error) {
mappings := make([]apicontract.AssetRelinkMapping, len(paths))
for i, path := range paths {
mappings[i].OldPath = path
}
return runAssetRelinks(ctx, mappings, true, true, true)
}
func RelinkAssets(ctx context.Context, mappings []apicontract.AssetRelinkMapping, dryRun bool) (apicontract.AssetReferencesData, error) {
return runAssetRelinks(ctx, mappings, dryRun, false, true)
}
func newAssetRelinkPlan(ctx context.Context, mappings []apicontract.AssetRelinkMapping, dryRun, lookup, batch bool) (*assetRelinkPlan, error) {
p := &assetRelinkPlan{ctx: ctx, batch: batch, lookup: lookup, assetRelinker: &assetRelinker{
collectOnly: true, routes: map[string]*assetRelinker{},
result: apicontract.AssetReferencesData{References: []apicontract.AssetReference{}, SkippedNotebooks: []string{}, DryRun: dryRun},
}}
if len(mappings) == 0 {
return p, errors.New("at least one asset path or mapping is required")
}
seen := map[string]bool{}
var validationErr error
for _, mapping := range mappings {
rule, err := newAssetRelinker(mapping.OldPath, mapping.NewPath)
if !lookup && mapping.NewPath == "" {
err = errors.New("newPath is required")
}
item := &assetRelinkItem{input: mapping, rule: rule}
p.items = append(p.items, item)
if rule.oldPath != "" {
if seen[rule.oldPath] {
validationErr = fmt.Errorf("duplicate oldPath: %s", mapping.OldPath)
}
seen[rule.oldPath] = true
}
if err != nil {
item.inputError = trueView on GitHub (pinned to 9f775e8a12)