dutchcoders/transfer.sh · warning
maxDate expired
Error message
maxDate expired
What it means
checkMetadata also enforces an optional expiry date stored in the file's metadata. If the metadata has a non-zero MaxDate and the current time is after it, the server refuses to serve the file and returns this error. It means the upload's time-to-live, as chosen by the sender, has elapsed.
Source
Thrown at server/handlers.go:888
func (s *Server) checkMetadata(ctx context.Context, token, filename string, increaseDownload bool) (metadata, 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 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 {View on GitHub (pinned to c37bfd9579)
Solutions
- Request the sender re-upload and share a fresh link with a later Max-Date.
- Upload with a longer expiry (larger --purge-days / appropriate Max-Date header) when the link must live longer.
- Verify server clock/NTP sync if files expire sooner than expected.
- If you control the deployment, purge/expiry policy can be tuned in checkMetadata or the purge job.
Example fix
// before curl -H 'Max-Date: 2026-01-01T00:00:00Z' -T f https://host/f # already past // after curl -H 'Max-Date: 2026-12-31T00:00:00Z' -T f https://host/f
Defensive patterns
Strategy: try-catch
Try / catch
resp, err := http.Get(url)
if err == nil {
body, _ := io.ReadAll(resp.Body)
if strings.Contains(string(body), "maxDate expired") {
// link expired: ask sender to re-upload
}
} Prevention
- Pick Max-Date well beyond the expected sharing window.
- Keep server clocks NTP-synced so expiry behaves predictably.
- Track link creation dates and re-share before expiry when needed.
When it happens
Trigger: Any download request (GET/HEAD/preview/zip/tar/tar.gz) for a token whose metadata contains MaxDate in the past, e.g. an upload created with a Max-Date header (or purge days) that has since passed.
Common situations: Recipient opens a shared link after the expiry window set by the sender; clocks skewed between server and client making a link appear expired early; very short expirations (minutes) combined with email/social delays.
Related errors
- maxDownloads expired
- could not encode metadata
- could not save metadata
- metadata doesn't exist
- deletion token doesn't match
AI-assisted analysis of dutchcoders/transfer.sh@c37bfd9579 (2026-09-05).
Data as JSON: /api/errors/a95003c9354dca1e.
Report an issue: GitHub.