Tencent/WeKnora · error

invalid file name: %w

Error message

invalid file name: %w

What it means

This error is returned by ossFileService.SaveBytes when utils.SafeFileName rejects the supplied fileName. SafeFileName sanitizes/validates user-provided names (strips path components, disallowed characters, empty names) and returns an error when the name cannot be made safe. The service wraps that error so callers know the failure was in name validation, not the OSS upload.

Source

Thrown at internal/application/service/file/oss.go:223

			Key:         oss.Ptr(objectName),
			Body:        src,
			ContentType: oss.Ptr(contentType),
		})
		if err != nil {
			return "", fmt.Errorf("failed to upload file to OSS: %w", err)
		}
	}

	return fmt.Sprintf("oss://%s/%s", s.bucketName, objectName), nil
}

// SaveBytes saves bytes data to OSS.
// If temp is true and temp bucket is configured, saves to temp bucket.
// Otherwise saves to main bucket.
func (s *ossFileService) SaveBytes(ctx context.Context, data []byte, tenantID uint64, fileName string, temp bool) (string, error) {
	safeName, err := utils.SafeFileName(fileName)
	if err != nil {
		return "", fmt.Errorf("invalid file name: %w", err)
	}
	ext := filepath.Ext(safeName)

	targetBucket := s.bucketName
	client := s.client
	objectName := fmt.Sprintf("%s%d/exports/%s%s", s.pathPrefix, tenantID, uuid.New().String(), ext)

	if temp && s.tempClient != nil {
		targetBucket = s.tempBucketName
		client = s.tempClient
		objectName = fmt.Sprintf("exports/%d/%s%s", tenantID, uuid.New().String(), ext)
	}

	_, err = client.PutObject(ctx, &oss.PutObjectRequest{
		Bucket:      oss.Ptr(targetBucket),
		Key:         oss.Ptr(objectName),
		Body:        bytes.NewReader(data),
		ContentType: oss.Ptr(utils.GetContentTypeByExt(ext)),

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Log/inspect the wrapped error from SafeFileName to see which rule failed.
  2. Sanitize the filename on the caller side before calling SaveBytes (strip directories, allow alphanumerics/-/_/.).
  3. Fall back to a generated default name when the original is invalid (the service already appends a UUID, so the name only matters for the extension).
  4. Add upstream validation at the API/ingest layer so bad names never reach the storage layer.

Example fix

// before
err := svc.SaveBytes(ctx, data, tenantID, rawUserFileName, false)
// after
safe, err := utils.SafeFileName(rawUserFileName)
if err != nil {
    safe = "export" + filepath.Ext(rawUserFileName)
}
err = svc.SaveBytes(ctx, data, tenantID, safe, false)
Defensive patterns

Strategy: validation

Validate before calling

func validFileName(name string) bool {
    if name == "" || len(name) > 255 { return false }
    if strings.ContainsAny(name, "/\\\x00") { return false }
    if strings.Contains(name, "..") { return false }
    return true
}
// call before SaveBytes
if !validFileName(fileName) { return errors.New("reject bad file name") }

Try / catch

if err := saveBytes(...); err != nil {
    if strings.Contains(err.Error(), "invalid file name") {
        // fall back to generated name or reject input
    }
}

Prevention

When it happens

Trigger: Calling SaveBytes with a fileName that is empty, contains path separators or traversal sequences (../), illegal characters (control chars, reserved names), or is otherwise rejected by utils.SafeFileName.

Common situations: Export pipelines passing raw user-uploaded filenames straight to SaveBytes; filenames containing Windows-reserved names or unicode oddities; empty fileName when the caller never set the original document name.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/ccf867b1ab665ddc. Report an issue: GitHub.