GopeedLab/gopeed · error

unsupported ed2k link type

Error message

unsupported ed2k link type

What it means

parseLink (internal/protocol/ed2k/fetcher.go:402-412) parses the string with goed2k.ParseEMuleLink successfully, but the link's Type is not goed2k.LinkFile. The eMule link scheme covers more than files — server links (ed2k://|server|ip|port|/) and server-list links are valid links that this downloader cannot fetch, so they are rejected explicitly.

Source

Thrown at internal/protocol/ed2k/fetcher.go:409

func (fm *FetcherManager) Close() error {
	fm.mu.Lock()
	defer fm.mu.Unlock()

	if fm.client != nil {
		fm.client.Close()
		fm.client = nil
	}
	return nil
}

func parseLink(raw string) (goed2k.EMuleLink, error) {
	link, err := goed2k.ParseEMuleLink(raw)
	if err != nil {
		return goed2k.EMuleLink{}, err
	}
	if link.Type != goed2k.LinkFile {
		return goed2k.EMuleLink{}, errors.New("unsupported ed2k link type")
	}
	return link, nil
}

func buildResource(link goed2k.EMuleLink) *base.Resource {
	return &base.Resource{
		Size:  link.NumberValue,
		Range: false,
		Hash:  link.Hash.String(),
		Files: []*base.FileInfo{
			{
				Name: link.StringValue,
				Size: link.NumberValue,
			},
		},
	}
}

View on GitHub (pinned to 7b7327ffb3)

Solutions

  1. Use only file links: ed2k://|file|<name>|<size>|<md4-hex>|/
  2. Filter candidate links before task creation: require the segment after ed2k://| to be 'file'
  3. Surface a clear 'not a downloadable ed2k file link' message in UI instead of retrying
  4. Check link.StringValue/NumberValue exist after parse if you need extra safety

Example fix

// before
_, err := downloader.Resolve(&base.Request{URL: "ed2k://|server|10.0.0.1|4661|/"}, nil)

// after
isFile := func(u string) bool { return strings.HasPrefix(u, "ed2k://|file|") }
if !isFile(u) { return errors.New("only ed2k file links are supported") }
_, err := downloader.Resolve(&base.Request{URL: u}, nil)
Defensive patterns

Strategy: validation

Validate before calling

func isEd2kFileLink(u string) bool {
    return strings.HasPrefix(strings.ToLower(u), "ed2k://|file|")
}
if !isEd2kFileLink(u) { return fmt.Errorf("unsupported ed2k link (need |file|): %s", u) }
_, err := downloader.Resolve(&base.Request{URL: u}, nil)

Type guard

func isEd2kFileLink(u string) bool { return strings.HasPrefix(strings.ToLower(u), "ed2k://|file|") }

Try / catch

if _, err := downloader.Resolve(req, nil); err != nil {
    if strings.Contains(err.Error(), "unsupported ed2k link type") {
        // tell the user only ed2k file links are downloadable; filter the input
    }
}

Prevention

When it happens

Trigger: Creating/resolving a task with an ed2k server link (ed2k://|server|207.62.153.10|4242|/) or server-list link instead of a file link; paste/clipboard bugs that grab the wrong link from a page of mixed ed2k links; parsing the 'file' variant with malformed segments such that goed2k still classifies it as a non-file type.

Common situations: Users pasting a server link copied from an eMule server list; indexers that return multiple ed2k link kinds; scripts iterating over ed2k:// URLs scraped from a page without filtering by the |file| segment.

Related errors


AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16). Data as JSON: /api/errors/7354662598d1713b. Report an issue: GitHub.