dutchcoders/transfer.sh · error

could not encode metadata

Error message

could not encode metadata

What it means

After incrementing the download counter, checkMetadata re-serializes the metadata to JSON and persists it back to storage. If json.Encoder fails to encode the in-memory metadata struct, this error is returned and the download is aborted. It indicates the metadata struct cannot be marshaled (essentially a programming/serialization invariant failure, since the struct is normally JSON-safe).

Source

Thrown at server/handlers.go:897

	if err != nil {
		return metadata, err
	}

	if err := json.NewDecoder(r).Decode(&metadata); err != nil {
		return metadata, err
	} else if metadata.MaxDownloads != -1 && metadata.Downloads >= metadata.MaxDownloads {
		return metadata, errors.New("maxDownloads expired")
	} else if !metadata.MaxDate.IsZero() && time.Now().After(metadata.MaxDate) {
		return metadata, errors.New("maxDate expired")
	} else if metadata.MaxDownloads != -1 && increaseDownload {
		// todo(nl5887): mutex?

		// update number of downloads
		metadata.Downloads++

		buffer := &bytes.Buffer{}
		if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
			return metadata, errors.New("could not encode metadata")
		} else if err := s.storage.Put(ctx, token, fmt.Sprintf("%s.metadata", filename), buffer, "text/json", uint64(buffer.Len())); err != nil {
			return metadata, errors.New("could not save metadata")
		}
	}

	return metadata, nil
}

func (s *Server) checkDeletionToken(ctx context.Context, deletionToken, token, filename string) error {
	s.lock(token, filename)
	defer s.unlock(token, filename)

	var metadata metadata

	r, _, err := s.storage.Get(ctx, token, fmt.Sprintf("%s.metadata", filename), nil)
	defer storage.CloseCheck(r)

	if s.storage.IsNotExist(err) {

View on GitHub (pinned to c37bfd9579)

Solutions

  1. Inspect server logs for the underlying json error and check which metadata field fails to marshal.
  2. Ensure the metadata struct only contains JSON-serializable fields (no channels, funcs, or unsupported types).
  3. Re-upload the file to regenerate clean metadata.
  4. Update/patch the server build if a version change altered the metadata schema; consider logging the raw error instead of discarding it.

Example fix

// before
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
	return metadata, errors.New("could not encode metadata")
}
// after
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
	return metadata, fmt.Errorf("could not encode metadata: %w", err)
}
Defensive patterns

Strategy: fallback

Try / catch

if err != nil && strings.Contains(err.Error(), "could not encode metadata") {
	// retry download without relying on counter update, or report server bug
	return retryDownload()
}

Prevention

When it happens

Trigger: checkMetadata with increaseDownload=true on a file with a finite MaxDownloads where json.NewEncoder(buffer).Encode(metadata) returns an error — practically only when the metadata struct holds an unmarshalable value (e.g. invalid field types or a corrupted in-memory state).

Common situations: Custom builds that added non-serializable fields to the metadata struct; metadata types changed between versions such that freshly decoded values cannot be re-encoded; corrupted metadata round-trips.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of dutchcoders/transfer.sh@c37bfd9579 (2026-09-05). Data as JSON: /api/errors/b098a61d3f9850c0. Report an issue: GitHub.