From 2f18bd461b33ee5638927fe598db4291d8871f34 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Thu, 29 Oct 2026 08:59:04 +0000 Subject: [PATCH 1/2] Explain why upload type recovery must be retained --- libs/filer/workspace_files_client.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/filer/workspace_files_client.go b/libs/filer/workspace_files_client.go index 30ca51f03d9..cd8e062fb60 100644 --- a/libs/filer/workspace_files_client.go +++ b/libs/filer/workspace_files_client.go @@ -257,6 +257,10 @@ func messageNames(re *regexp.Regexp, msg, name string) bool { // deleteNodeOfOtherType deletes the node that blocks an overwrite of absPath // because its type differs from the upload's, and reports whether it did. // CLI v1.21 and v1.22 uploaded some notebooks as files this way. +// +// Changes to how uploads are classified as files or notebooks can leave existing +// nodes with the previous type. Keep this recovery path so future classification +// changes do not break redeployments: overwrite alone cannot change a node's type. func (w *WorkspaceFilesClient) deleteNodeOfOtherType(ctx context.Context, absPath string, uploadErr error) (bool, error) { aerr, ok := errors.AsType[*apierr.APIError](uploadErr) if !ok { From b5781d1f65e99c83fefff03ba306e405a9bd9bb8 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Thu, 29 Oct 2026 09:03:02 +0000 Subject: [PATCH 2/2] Document upload classification regression and recovery lifetime --- libs/filer/workspace_files_client.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/libs/filer/workspace_files_client.go b/libs/filer/workspace_files_client.go index cd8e062fb60..ee026873233 100644 --- a/libs/filer/workspace_files_client.go +++ b/libs/filer/workspace_files_client.go @@ -256,11 +256,22 @@ func messageNames(re *regexp.Regexp, msg, name string) bool { // deleteNodeOfOtherType deletes the node that blocks an overwrite of absPath // because its type differs from the upload's, and reports whether it did. -// CLI v1.21 and v1.22 uploaded some notebooks as files this way. // -// Changes to how uploads are classified as files or notebooks can leave existing -// nodes with the previous type. Keep this recovery path so future classification -// changes do not break redeployments: overwrite alone cannot change a node's type. +// Regression: CLI v1.21 switched from /workspace-files/import-file to +// /workspace/import (https://github.com/databricks/cli/pull/6149). The follow-up +// https://github.com/databricks/cli/pull/7034 added client-side notebook detection. +// These upload paths use different rules to recognize notebooks. For example, +// import-file accepts a notebook marker anywhere on the first line, but the CLI +// required an exact header match. A SQL notebook with a UTF-8 BOM was therefore +// uploaded as a file in v1.21/v1.22. +// +// Recovery: https://github.com/databricks/cli/pull/7218 restored import-file, so +// the same bytes can now be recognized as a notebook. Overwrite cannot change +// an existing node's type; delete and retry to keep those deployments working +// after an upgrade. +// +// Removal: this compatibility code can be removed once the risk of users +// upgrading directly from v1.21/v1.22 to the latest CLI is negligible. func (w *WorkspaceFilesClient) deleteNodeOfOtherType(ctx context.Context, absPath string, uploadErr error) (bool, error) { aerr, ok := errors.AsType[*apierr.APIError](uploadErr) if !ok {