This is an automated email from the ASF dual-hosted git repository.

JHoelli pushed a commit to branch marking_pipeline_falsely_as_rewuire_attention
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit faa93cd09f661db7b8470fa37f2da82285ba325e
Author: Jacqueline Höllig <[email protected]>
AuthorDate: Mon Nov 2 09:28:23 2026 +0100

    fix: preserve pipelines on extension outages
---
 .../model/connect/adapter/PipelineUpdateInfo.java  |  9 ++++
 .../CustomTransformOutputSchemaGenerator.java      |  3 +-
 .../output/OutputSchemaUnavailableException.java   | 36 +++++++++++++
 .../pipeline/update/PipelineUpdateCoordinator.java | 61 +++++++++++++++++++---
 .../CustomTransformOutputSchemaGeneratorTest.java  | 18 +++++++
 .../update/PipelineUpdateCoordinatorTest.java      | 57 ++++++++++++++++++++
 ui/deployment/i18n/de.json                         |  4 +-
 ui/deployment/i18n/en.json                         |  4 +-
 ui/deployment/i18n/pl.json                         |  4 +-
 .../src/lib/model/gen/streampipes-model-client.ts  | 12 +++--
 .../src/lib/model/gen/streampipes-model.ts         |  7 ++-
 ...adapter-started-update-migration.component.html | 28 +++++++++-
 12 files changed, 220 insertions(+), 23 deletions(-)

diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/PipelineUpdateInfo.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/PipelineUpdateInfo.java
index 8ee7184720..d77bd240ba 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/PipelineUpdateInfo.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/PipelineUpdateInfo.java
@@ -33,6 +33,7 @@ public class PipelineUpdateInfo {
   private String pipelineName;
   private boolean canAutoMigrate;
   private String migrationInfo;
+  private boolean validationUnavailable;
   private Map<String, List<PipelineElementValidationInfo>> validationInfos;
   private List<ChartSchemaUpdateInfo> chartSchemaUpdateInfos;
 
@@ -73,6 +74,14 @@ public class PipelineUpdateInfo {
     this.migrationInfo = migrationInfo;
   }
 
+  public boolean isValidationUnavailable() {
+    return validationUnavailable;
+  }
+
+  public void setValidationUnavailable(boolean validationUnavailable) {
+    this.validationUnavailable = validationUnavailable;
+  }
+
   public Map<String, List<PipelineElementValidationInfo>> getValidationInfos() 
{
     return validationInfos;
   }
diff --git 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGenerator.java
 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGenerator.java
index c9ee72c879..8f8a3da94d 100644
--- 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGenerator.java
+++ 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGenerator.java
@@ -94,8 +94,7 @@ public class CustomTransformOutputSchemaGenerator extends 
OutputSchemaGenerator<
       var response = 
requestManager.request(ExtensionServiceRequests.outputSchema(requestTarget, 
httpRequestBody));
       return handleResponse(response);
     } catch (Exception e) {
-      e.printStackTrace();
-      return new EventSchema();
+      throw new 
OutputSchemaUnavailableException(dataProcessorInvocation.getAppId(), e);
     }
   }
 
diff --git 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/OutputSchemaUnavailableException.java
 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/OutputSchemaUnavailableException.java
new file mode 100644
index 0000000000..498d08ca8c
--- /dev/null
+++ 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/output/OutputSchemaUnavailableException.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.manager.matching.output;
+
+/**
+ * Signals that a custom output schema could not be determined from its 
extension service.
+ */
+public class OutputSchemaUnavailableException extends RuntimeException {
+
+  private final String appId;
+
+  public OutputSchemaUnavailableException(String appId, Throwable cause) {
+    super("Could not compute the output schema for pipeline element " + appId, 
cause);
+    this.appId = appId;
+  }
+
+  public String getAppId() {
+    return appId;
+  }
+}
diff --git 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinator.java
 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinator.java
index 7405727c07..469fcbec46 100644
--- 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinator.java
+++ 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinator.java
@@ -22,12 +22,15 @@ import 
org.apache.streampipes.commons.prometheus.pipelines.PipelinesStats;
 import 
org.apache.streampipes.manager.api.extensions.ExtensionServiceRequestManager;
 import org.apache.streampipes.manager.execution.PipelineExecutor;
 import org.apache.streampipes.manager.matching.PipelineVerificationHandlerV2;
+import 
org.apache.streampipes.manager.matching.output.OutputSchemaUnavailableException;
 import 
org.apache.streampipes.manager.matching.v2.pipeline.MeasurementChangeValidationStep;
 import org.apache.streampipes.manager.pipeline.PipelineElementUserCleaner;
 import org.apache.streampipes.manager.pipeline.PipelineManager;
 import org.apache.streampipes.model.SpDataStream;
 import org.apache.streampipes.model.base.NamedStreamPipesEntity;
 import org.apache.streampipes.model.connect.adapter.PipelineUpdateInfo;
+import org.apache.streampipes.model.graph.DataProcessorInvocation;
+import org.apache.streampipes.model.graph.DataSinkInvocation;
 import org.apache.streampipes.model.message.PipelineModificationMessage;
 import org.apache.streampipes.model.pipeline.Pipeline;
 import org.apache.streampipes.model.pipeline.PipelineElementValidationInfo;
@@ -90,12 +93,9 @@ public class PipelineUpdateCoordinator {
 
     affectedPipelines.forEach(pipeline -> {
       var shouldRestartPipeline = pipeline.isRunning();
-      if (shouldRestartPipeline) {
-        new PipelineExecutor(pipeline, requestManager, 
resourceManager).stopPipeline(true);
-      }
-
       var storedPipeline = 
pipelineManager.getPipeline(pipeline.getPipelineId());
-      var updatedPipeline = updatePipeline(storedPipeline, affectedElementId, 
updatedStreamName, updatedEventSchema);
+      var updatedPipeline = updatePipeline(
+          copyPipeline(storedPipeline), affectedElementId, updatedStreamName, 
updatedEventSchema);
 
       try {
         var verificationHandler = new 
PipelineVerificationHandlerV2(resourceManager.getServiceDiscovery(), 
updatedPipeline, requestManager);
@@ -119,6 +119,11 @@ public class PipelineUpdateCoordinator {
           modifiedPipeline.setValid(false);
         }
 
+        if (shouldRestartPipeline) {
+          new PipelineExecutor(pipeline, requestManager, 
resourceManager).stopPipeline(true);
+          modifiedPipeline.setRunning(false);
+          
modifiedPipeline.setRev(pipelineManager.getPipeline(pipeline.getPipelineId()).getRev());
+        }
         PipelineElementUserCleaner.clearCorrespondingUsers(modifiedPipeline);
         pipelineStorage.updateElement(modifiedPipeline);
 
@@ -127,6 +132,9 @@ public class PipelineUpdateCoordinator {
               pipelineManager.getPipeline(pipeline.getPipelineId()), 
requestManager, resourceManager
           ).startPipeline();
         }
+      } catch (OutputSchemaUnavailableException e) {
+        LOG.warn("Skipped pipeline update for {} because the output schema for 
{} is unavailable",
+            storedPipeline.getName(), e.getAppId(), e);
       } catch (Exception e) {
         LOG.error("Could not update pipeline {}", updatedPipeline.getName(), 
e);
       }
@@ -140,7 +148,8 @@ public class PipelineUpdateCoordinator {
     var pipelineUpdateInfos = new ArrayList<PipelineUpdateInfo>();
 
     affectedPipelines.forEach(pipeline -> {
-      var updatedPipeline = updatePipeline(pipeline, affectedElementId, 
updatedStreamName, updatedEventSchema);
+      var updatedPipeline = updatePipeline(
+          copyPipeline(pipeline), affectedElementId, updatedStreamName, 
updatedEventSchema);
       try {
         var verificationHandler = new 
PipelineVerificationHandlerV2(resourceManager.getServiceDiscovery(), 
updatedPipeline, requestManager);
         var modificationMessage = verificationHandler.verifyPipeline();
@@ -148,6 +157,8 @@ public class PipelineUpdateCoordinator {
         updateInfo.setChartSchemaUpdateInfos(
             chartSchemaUpdateCoordinator.checkChartMigrations(updatedPipeline, 
updatedEventSchema));
         pipelineUpdateInfos.add(updateInfo);
+      } catch (OutputSchemaUnavailableException e) {
+        pipelineUpdateInfos.add(makeUnavailableUpdateInfo(pipeline, e));
       } catch (Exception e) {
         throw new RuntimeException(e);
       }
@@ -156,6 +167,44 @@ public class PipelineUpdateCoordinator {
     return pipelineUpdateInfos;
   }
 
+  private Pipeline copyPipeline(Pipeline pipeline) {
+    var copy = pipeline.clone();
+    copy.setRunning(pipeline.isRunning());
+    copy.setRestartOnSystemReboot(pipeline.isRestartOnSystemReboot());
+    copy.setStartedAt(pipeline.getStartedAt());
+    copy.setPublicElement(pipeline.isPublicElement());
+    copy.setLabels(new ArrayList<>(pipeline.getLabels()));
+    copy.setLastMigratedAt(pipeline.getLastMigratedAt());
+    copy.setPipelineNotifications(new 
ArrayList<>(pipeline.getPipelineNotifications()));
+    
copy.setStreams(pipeline.getStreams().stream().map(SpDataStream::new).toList());
+    
copy.setSepas(pipeline.getSepas().stream().map(this::copyProcessor).toList());
+    
copy.setActions(pipeline.getActions().stream().map(this::copySink).toList());
+    return copy;
+  }
+
+  private DataProcessorInvocation copyProcessor(DataProcessorInvocation 
processor) {
+    var copy = new DataProcessorInvocation(processor);
+    copy.setSelectedServiceId(processor.getSelectedServiceId());
+    return copy;
+  }
+
+  private DataSinkInvocation copySink(DataSinkInvocation sink) {
+    var copy = new DataSinkInvocation(sink);
+    copy.setSelectedServiceId(sink.getSelectedServiceId());
+    return copy;
+  }
+
+  private PipelineUpdateInfo makeUnavailableUpdateInfo(Pipeline pipeline,
+                                                       
OutputSchemaUnavailableException exception) {
+    var updateInfo = new PipelineUpdateInfo();
+    updateInfo.setPipelineId(pipeline.getPipelineId());
+    updateInfo.setPipelineName(pipeline.getName());
+    updateInfo.setCanAutoMigrate(false);
+    updateInfo.setValidationUnavailable(true);
+    updateInfo.setMigrationInfo(exception.getMessage());
+    return updateInfo;
+  }
+
   private Pipeline updatePipeline(Pipeline pipeline,
                                   String affectedElementId,
                                   String updatedStreamName,
diff --git 
a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGeneratorTest.java
 
b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGeneratorTest.java
index a9986ab55c..2e35fbef98 100644
--- 
a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGeneratorTest.java
+++ 
b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/matching/output/CustomTransformOutputSchemaGeneratorTest.java
@@ -33,6 +33,7 @@ import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 
@@ -65,6 +66,23 @@ class CustomTransformOutputSchemaGeneratorTest {
     assertTrue(secretProperty.getEncrypted());
   }
 
+  @Test
+  void throwsWhenTheExtensionCannotComputeTheOutputSchema() {
+    var invocation = new DataProcessorInvocation();
+    invocation.setAppId("org.apache.streampipes.test.processor");
+    var generator = new CustomTransformOutputSchemaGenerator(
+        mock(ISpServiceDiscovery.class),
+        new CustomTransformOutputStrategy(),
+        invocation,
+        mock(ExtensionServiceRequestManager.class)
+    );
+
+    var exception = assertThrows(OutputSchemaUnavailableException.class,
+        () -> generator.buildFromOneStream(null));
+
+    assertEquals(invocation.getAppId(), exception.getAppId());
+  }
+
   private SecretStaticProperty makeSecretProperty(String value,
                                                   boolean encrypted) {
     var secretProperty = new SecretStaticProperty("secret", "Secret", "");
diff --git 
a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinatorTest.java
 
b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinatorTest.java
index 7927b61ebf..1a610a1917 100644
--- 
a/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinatorTest.java
+++ 
b/streampipes-pipeline-management/src/test/java/org/apache/streampipes/manager/pipeline/update/PipelineUpdateCoordinatorTest.java
@@ -22,6 +22,7 @@ import org.apache.streampipes.audit.api.AuditService;
 import 
org.apache.streampipes.manager.api.extensions.ExtensionServiceRequestManager;
 import org.apache.streampipes.manager.execution.PipelineExecutor;
 import org.apache.streampipes.manager.matching.PipelineVerificationHandlerV2;
+import 
org.apache.streampipes.manager.matching.output.OutputSchemaUnavailableException;
 import 
org.apache.streampipes.manager.matching.v2.pipeline.MeasurementChangeValidationStep;
 import org.apache.streampipes.model.SpDataStream;
 import org.apache.streampipes.model.connect.adapter.PipelineUpdateInfo;
@@ -57,6 +58,7 @@ import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -190,6 +192,35 @@ class PipelineUpdateCoordinatorTest {
     }
   }
 
+  @Test
+  void updatePipelines_ShouldPreservePipelineWhenOutputSchemaIsUnavailable() {
+    var requestManager = mock(ExtensionServiceRequestManager.class);
+    var resourceManager = mock(SpResourceManager.class);
+    var pipelineStorage = mock(IPipelineStorage.class);
+    var coordinator = makeCoordinator(requestManager, resourceManager, 
pipelineStorage);
+    var dataStream = makeDataStream("stream-1", "Updated stream");
+    var storedPipeline = makePipeline("pipeline-1", "Pipeline", true, 
"stream-1", "Old stream");
+    when(pipelineStorage.findAll()).thenReturn(List.of(storedPipeline));
+    
when(pipelineStorage.getElementById("pipeline-1")).thenReturn(storedPipeline);
+
+    try (MockedConstruction<PipelineVerificationHandlerV2> 
verificationHandlerConstruction =
+             mockConstruction(PipelineVerificationHandlerV2.class, (mock, 
context) ->
+                 when(mock.verifyPipeline()).thenThrow(new 
OutputSchemaUnavailableException("math-expression",
+                     new RuntimeException("Service unavailable"))));
+         MockedConstruction<PipelineExecutor> executorConstruction =
+             mockConstruction(PipelineExecutor.class)) {
+
+      coordinator.updatePipelines(dataStream);
+
+      assertEquals(1, verificationHandlerConstruction.constructed().size());
+      assertEquals(0, executorConstruction.constructed().size());
+      verify(pipelineStorage, never()).updateElement(storedPipeline);
+      assertTrue(storedPipeline.isRunning());
+      assertTrue(storedPipeline.isValid());
+      assertEquals("Old stream", 
storedPipeline.getStreams().getFirst().getName());
+    }
+  }
+
   @Test
   void checkPipelineMigrations_ShouldUseUpdatedDataStreamValues() {
     var requestManager = mock(ExtensionServiceRequestManager.class);
@@ -262,6 +293,32 @@ class PipelineUpdateCoordinatorTest {
     }
   }
 
+  @Test
+  void 
checkPipelineMigrations_ShouldReportUnavailableOutputSchemaWithoutMutatingThePipeline()
 {
+    var requestManager = mock(ExtensionServiceRequestManager.class);
+    var resourceManager = mock(SpResourceManager.class);
+    var pipelineStorage = mock(IPipelineStorage.class);
+    var coordinator = makeCoordinator(requestManager, resourceManager, 
pipelineStorage);
+    var dataStream = makeDataStream("stream-1", "Updated stream");
+    var pipeline = makePipeline("pipeline-1", "Pipeline", true, "stream-1", 
"Old stream");
+    when(pipelineStorage.findAll()).thenReturn(List.of(pipeline));
+
+    try (MockedConstruction<PipelineVerificationHandlerV2> 
verificationHandlerConstruction =
+             mockConstruction(PipelineVerificationHandlerV2.class, (mock, 
context) ->
+                 when(mock.verifyPipeline()).thenThrow(new 
OutputSchemaUnavailableException("math-expression",
+                     new RuntimeException("Service unavailable"))))) {
+
+      var result = coordinator.checkPipelineMigrations(dataStream);
+
+      assertEquals(1, verificationHandlerConstruction.constructed().size());
+      assertEquals(1, result.size());
+      assertTrue(result.getFirst().isValidationUnavailable());
+      assertFalse(result.getFirst().isCanAutoMigrate());
+      
assertTrue(result.getFirst().getMigrationInfo().contains("math-expression"));
+      assertEquals("Old stream", pipeline.getStreams().getFirst().getName());
+    }
+  }
+
   @Test
   void 
checkPipelineMigrations_ShouldDisableAutoMigrationForCriticalMeasurementFieldChange()
 {
     var requestManager = mock(ExtensionServiceRequestManager.class);
diff --git a/ui/deployment/i18n/de.json b/ui/deployment/i18n/de.json
index 466d1b4cdf..8adad43d32 100644
--- a/ui/deployment/i18n/de.json
+++ b/ui/deployment/i18n/de.json
@@ -138,7 +138,6 @@
   "Assign additional labels to better discover your assets": "Weisen Sie 
zusätzliche Labels zu, um Ihre Assets besser zu finden",
   "Attach adapters, dashboards, or pipelines in the asset editor to surface 
them here.": "Fügen Sie Adapter, Dashboards oder Pipelines im Asset-Editor 
hinzu, um sie hier anzuzeigen.",
   "Audit Log": "Audit-Protokoll",
-  "Audit events could not be downloaded. Try again.": "Audit-Ereignisse 
konnten nicht heruntergeladen werden. Versuche es erneut.",
   "Audit events could not be loaded. Check the filters and storage 
availability, then retry.": "Audit-Ereignisse konnten nicht geladen werden. 
Prüfe die Filter und die Speicherverfügbarkeit und versuche es erneut.",
   "Audit pages": "Audit-Seiten",
   "Audit recording is disabled. Enable auditing in the Core deployment 
configuration.": "Die Audit-Aufzeichnung ist deaktiviert. Aktiviere sie in der 
Bereitstellungskonfiguration des Core.",
@@ -889,7 +888,6 @@
   "Please wait while the pipeline is stopping": "Bitte warten Sie, während die 
Pipeline gestoppt wird",
   "Port": "Port",
   "Possible placeholders:": "Mögliche Platzhalter:",
-  "Preparing download...": "Download wird vorbereitet...",
   "Preparing pipeline editor...": "Pipeline-Editor vorbereiten...",
   "Press 'Next' to start the process.": "Auf \"Weiter\" drücken, um den 
Vorgang zu starten.",
   "Press Next to start the process.": "Klicken Sie auf Weiter, um den Vorgang 
zu starten.",
@@ -1260,6 +1258,7 @@
   "This operation cannot be undone.": "Dieser Vorgang kann nicht rückgängig 
gemacht werden.",
   "This operation cannot be undone. Please ensure that the data provider is 
not used in a datalake retention.": "Dieser Vorgang kann nicht rückgängig 
gemacht werden. Bitte stellen Sie sicher, dass der Provider in keiner 
Speicherrichtlinie verwendet wird.",
   "This pipeline cannot be updated because at least one data lake measurement 
field changed its datatype.": "Diese Pipeline kann nicht aktualisiert werden, 
da sich der Datentyp mindestens eines Data-Lake-Messfelds geändert hat.",
+  "This pipeline could not be revalidated because a required extension is 
unavailable. Its configuration will remain unchanged.": "Diese Pipeline konnte 
nicht erneut validiert werden, weil eine erforderliche Erweiterung nicht 
verfügbar ist. Ihre Konfiguration bleibt unverändert.",
   "This pipeline is still running.": "Diese Pipeline ist noch in Betrieb.",
   "This pipeline update requires manual review.": "Diese 
Pipeline-Aktualisierung erfordert eine manuelle Prüfung.",
   "This pipeline will be automatically migrated.": "Diese Pipeline wird 
automatisch migriert.",
@@ -1415,7 +1414,6 @@
   "You need to delete those pipelines first before deleting the adapter.": 
"Sie müssen diese Pipelines zuerst löschen, bevor Sie den Adapter löschen 
können.",
   "Your Assets were successfully added.": "Assets erfolgreich hinzugefügt.",
   "Your Assets were successfully deleted.": "Assets erfolgreich gelöscht.",
-  "Your audit log is being downloaded.": "Dein Audit-Protokoll wird 
heruntergeladen.",
   "Your new API key has been created. Please copy the key now - you won't be 
able to see the key again.": "Ihr neuer API-Schlüssel wurde erstellt. Bitte 
kopieren Sie den Schlüssel jetzt - Sie werden ihn nicht mehr sehen können.",
   "Your new data stream is now available in the pipeline editor.": "Ihr neuer 
Datenstrom ist nun im Pipeline-Editor verfügbar.",
   "Your password successfully changed.": "Ihr Passwort wurde erfolgreich 
geändert.",
diff --git a/ui/deployment/i18n/en.json b/ui/deployment/i18n/en.json
index 4a078bc89e..96d6c8b72e 100644
--- a/ui/deployment/i18n/en.json
+++ b/ui/deployment/i18n/en.json
@@ -138,7 +138,6 @@
   "Assign additional labels to better discover your assets": null,
   "Attach adapters, dashboards, or pipelines in the asset editor to surface 
them here.": null,
   "Audit Log": "Audit Log",
-  "Audit events could not be downloaded. Try again.": null,
   "Audit events could not be loaded. Check the filters and storage 
availability, then retry.": "Audit events could not be loaded. Check the 
filters and storage availability, then retry.",
   "Audit pages": "Audit pages",
   "Audit recording is disabled. Enable auditing in the Core deployment 
configuration.": "Audit recording is disabled. Enable auditing in the Core 
deployment configuration.",
@@ -889,7 +888,6 @@
   "Please wait while the pipeline is stopping": null,
   "Port": null,
   "Possible placeholders:": null,
-  "Preparing download...": null,
   "Preparing pipeline editor...": null,
   "Press 'Next' to start the process.": null,
   "Press Next to start the process.": null,
@@ -1260,6 +1258,7 @@
   "This operation cannot be undone.": null,
   "This operation cannot be undone. Please ensure that the data provider is 
not used in a datalake retention.": null,
   "This pipeline cannot be updated because at least one data lake measurement 
field changed its datatype.": null,
+  "This pipeline could not be revalidated because a required extension is 
unavailable. Its configuration will remain unchanged.": null,
   "This pipeline is still running.": null,
   "This pipeline update requires manual review.": null,
   "This pipeline will be automatically migrated.": null,
@@ -1415,7 +1414,6 @@
   "You need to delete those pipelines first before deleting the adapter.": 
null,
   "Your Assets were successfully added.": null,
   "Your Assets were successfully deleted.": null,
-  "Your audit log is being downloaded.": null,
   "Your new API key has been created. Please copy the key now - you won't be 
able to see the key again.": null,
   "Your new data stream is now available in the pipeline editor.": null,
   "Your password successfully changed.": null,
diff --git a/ui/deployment/i18n/pl.json b/ui/deployment/i18n/pl.json
index 4ff0f740a8..7829c5162d 100644
--- a/ui/deployment/i18n/pl.json
+++ b/ui/deployment/i18n/pl.json
@@ -138,7 +138,6 @@
   "Assign additional labels to better discover your assets": "Przypisz 
dodatkowe etykiety, aby łatwiej odnajdywać zasoby",
   "Attach adapters, dashboards, or pipelines in the asset editor to surface 
them here.": "Dołącz adaptery, pulpity lub strumienie w edytorze zasobu, aby 
wyświetlały się tutaj.",
   "Audit Log": "Dziennik audytu",
-  "Audit events could not be downloaded. Try again.": "Nie udało się pobrać 
zdarzeń audytu. Spróbuj ponownie.",
   "Audit events could not be loaded. Check the filters and storage 
availability, then retry.": "Nie udało się wczytać zdarzeń audytu. Sprawdź 
filtry i dostępność magazynu, a następnie spróbuj ponownie.",
   "Audit pages": "Strony audytu",
   "Audit recording is disabled. Enable auditing in the Core deployment 
configuration.": "Rejestrowanie audytu jest wyłączone. Włącz je w konfiguracji 
wdrożenia Core.",
@@ -889,7 +888,6 @@
   "Please wait while the pipeline is stopping": "Proszę czekać, trwa 
zatrzymywanie strumienia",
   "Port": "Port",
   "Possible placeholders:": "Możliwe zastępniki:",
-  "Preparing download...": "Przygotowywanie pobierania...",
   "Preparing pipeline editor...": "Przygotowywanie edytora strumieni...",
   "Press 'Next' to start the process.": "Naciśnij „Dalej”, aby rozpocząć 
proces.",
   "Press Next to start the process.": "Kliknij Dalej, aby rozpocząć proces.",
@@ -1260,6 +1258,7 @@
   "This operation cannot be undone.": "Tego działania nie można cofnąć.",
   "This operation cannot be undone. Please ensure that the data provider is 
not used in a datalake retention.": "Tego działania nie można cofnąć. Upewnij 
się, że dostawca nie jest używany w retencji Data Lake.",
   "This pipeline cannot be updated because at least one data lake measurement 
field changed its datatype.": "Nie można zaktualizować tego strumienia, 
ponieważ co najmniej jedno pole miary Data Lake zmieniło typ danych.",
+  "This pipeline could not be revalidated because a required extension is 
unavailable. Its configuration will remain unchanged.": "Nie można było 
ponownie zweryfikować tego strumienia, ponieważ wymagana wtyczka jest 
niedostępna. Jego konfiguracja pozostanie bez zmian.",
   "This pipeline is still running.": "Ten strumień nadal działa.",
   "This pipeline update requires manual review.": "Ta aktualizacja strumienia 
wymaga ręcznego sprawdzenia.",
   "This pipeline will be automatically migrated.": "Ten strumień zostanie 
automatycznie zmigrowany.",
@@ -1415,7 +1414,6 @@
   "You need to delete those pipelines first before deleting the adapter.": 
"Przed usunięciem adaptera najpierw usuń te strumienie.",
   "Your Assets were successfully added.": "Twoje zasoby zostały pomyślnie 
dodane.",
   "Your Assets were successfully deleted.": "Twoje zasoby zostały pomyślnie 
usunięte.",
-  "Your audit log is being downloaded.": "Twój dziennik audytu jest 
pobierany.",
   "Your new API key has been created. Please copy the key now - you won't be 
able to see the key again.": "Twój nowy klucz API został utworzony. Skopiuj go 
teraz - później nie będzie już widoczny.",
   "Your new data stream is now available in the pipeline editor.": "Twój nowy 
strumień danych jest teraz dostępny w edytorze strumieńów.",
   "Your password successfully changed.": "Twoje hasło zostało pomyślnie 
zmienione.",
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
index d139164460..bd47318c8b 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model-client.ts
@@ -16,10 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-// @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2026-09-18 
15:38:46.
+/* tslint:disable */
+/* eslint-disable */
+// Generated using typescript-generator version 3.2.1263 on 2026-11-02 
09:03:42.
 
-import { Storable } from './streampipes-model';
+import { Storable } from '@streampipes/platform-services';
 
 export class Group implements Storable {
     alternateIds: string[];
@@ -237,6 +238,11 @@ export class ServiceAccount extends Principal {
     }
 }
 
+export interface Storable {
+    elementId: string;
+    rev: string;
+}
+
 export class UserAccount extends Principal {
     createdAtMillis: number;
     darkMode: boolean;
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 92cf0d4c2e..53d461344e 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -16,8 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-// @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2026-10-26 
15:02:34.
+/* tslint:disable */
+/* eslint-disable */
+// Generated using typescript-generator version 3.2.1263 on 2026-11-02 
09:03:36.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -3316,6 +3317,7 @@ export class PipelineUpdateInfo {
     pipelineId: string;
     pipelineName: string;
     validationInfos: { [index: string]: PipelineElementValidationInfo[] };
+    validationUnavailable: boolean;
 
     static fromData(
         data: PipelineUpdateInfo,
@@ -3335,6 +3337,7 @@ export class PipelineUpdateInfo {
         instance.validationInfos = __getCopyObjectFn(
             __getCopyArrayFn(PipelineElementValidationInfo.fromData),
         )(data.validationInfos);
+        instance.validationUnavailable = data.validationUnavailable;
         return instance;
     }
 }
diff --git 
a/ui/src/app/connect/dialog/adapter-started/adapter-started-update-migration/adapter-started-update-migration.component.html
 
b/ui/src/app/connect/dialog/adapter-started/adapter-started-update-migration/adapter-started-update-migration.component.html
index 4775d0f3db..b13f513426 100644
--- 
a/ui/src/app/connect/dialog/adapter-started/adapter-started-update-migration/adapter-started-update-migration.component.html
+++ 
b/ui/src/app/connect/dialog/adapter-started/adapter-started-update-migration/adapter-started-update-migration.component.html
@@ -61,7 +61,33 @@
                             </div>
                         </div>
                     }
-                    @if (!updateInfo.canAutoMigrate) {
+                    @if (updateInfo.validationUnavailable) {
+                        <div
+                            class="pipeline-status"
+                            fxLayoutAlign="start center"
+                            
data-cy="adapter-pipeline-validation-unavailable-warning"
+                        >
+                            <mat-icon class="status-icon status-icon-warning">
+                                warning
+                            </mat-icon>
+                            <div>
+                                <div class="pipeline-title">
+                                    {{ 'Pipeline' | translate }}
+                                    <b>{{ updateInfo.pipelineName }}</b>
+                                </div>
+                                <div class="pipeline-description">
+                                    {{
+                                        'This pipeline could not be 
revalidated because a required extension is unavailable. Its configuration will 
remain unchanged.'
+                                            | translate
+                                    }}
+                                </div>
+                            </div>
+                        </div>
+                    }
+                    @if (
+                        !updateInfo.canAutoMigrate &&
+                        !updateInfo.validationUnavailable
+                    ) {
                         <div
                             class="pipeline-status"
                             fxLayoutAlign="start center"

Reply via email to