diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java
index 92fd70593baaf23644cdde58b20e60bd9571c1a8..6bf838be637794609ef3417a5bf7e1ca2eec789a 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java
@@ -69,6 +69,8 @@ public class DataSetMetadataPanel extends JPanel
 
     private final DataSetUploadClientModel clientModel;
 
+    private final JLabel ownerIdLabel;
+
     private final JTextField ownerIdText;
 
     private final ButtonGroup ownerButtonGroup;
@@ -77,6 +79,8 @@ public class DataSetMetadataPanel extends JPanel
 
     private final JPanel dataSetTypePanel;
 
+    private final JLabel dataSetFileLabel;
+
     private final JComboBox dataSetFileComboBox;
 
     private final JButton dataSetFileButton;
@@ -100,6 +104,7 @@ public class DataSetMetadataPanel extends JPanel
         this.mainWindow = mainWindow;
 
         // Initialize the fields in the gui
+        ownerIdLabel = new JLabel("Owner:", JLabel.TRAILING);
         ownerIdText = new JTextField();
         ownerButtonGroup = new ButtonGroup();
         experimentButton = new JRadioButton("Experiment");
@@ -114,6 +119,7 @@ public class DataSetMetadataPanel extends JPanel
             { EMPTY_FILE_SELECTION };
         dataSetFileComboBox = new JComboBox(initialOptions);
         dataSetFileButton = new JButton("Browse...");
+        dataSetFileLabel = new JLabel("File:", JLabel.TRAILING);
 
         createGui();
     }
@@ -162,6 +168,7 @@ public class DataSetMetadataPanel extends JPanel
         }
 
         updateFileLabel();
+        syncErrors();
     }
 
     private void enableAllWidgets()
@@ -200,8 +207,7 @@ public class DataSetMetadataPanel extends JPanel
     private void createGui()
     {
         // The file row
-        JLabel label = new JLabel("File:", JLabel.TRAILING);
-        label.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT));
+        dataSetFileLabel.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT));
 
         dataSetFileComboBox.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
         dataSetFileComboBox.addItemListener(new ItemListener()
@@ -223,7 +229,7 @@ public class DataSetMetadataPanel extends JPanel
                         newDataSetInfo.getNewDataSetBuilder().setFile((File) selectedItem);
                     }
 
-                    notifyObserversOfChanges();
+                    validateAndNotifyObserversOfChanges();
                 }
 
             });
@@ -247,16 +253,15 @@ public class DataSetMetadataPanel extends JPanel
                         clientModel.userDidSelectFile(newDirOrNull);
                         updateFileComboBoxList();
                         updateFileLabel();
-                        notifyObserversOfChanges();
+                        validateAndNotifyObserversOfChanges();
                     }
                 }
 
             });
-        addRow(1, label, dataSetFileComboBox, dataSetFileButton);
+        addRow(1, dataSetFileLabel, dataSetFileComboBox, dataSetFileButton);
 
         // The owner row
-        label = new JLabel("Owner:", JLabel.TRAILING);
-        label.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT));
+        ownerIdLabel.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT));
 
         ownerIdText.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
         ownerIdText.addActionListener(new ActionListener()
@@ -299,10 +304,10 @@ public class DataSetMetadataPanel extends JPanel
                 }
             });
 
-        addRow(2, label, ownerIdText, ownerButtonGroup);
+        addRow(2, ownerIdLabel, ownerIdText, ownerButtonGroup);
 
         // The data set type row
-        label = new JLabel("Data Set Type:", JLabel.TRAILING);
+        JLabel label = new JLabel("Data Set Type:", JLabel.TRAILING);
         label.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT));
 
         dataSetTypeComboBox.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
@@ -466,9 +471,10 @@ public class DataSetMetadataPanel extends JPanel
         return mainWindow;
     }
 
-    private void notifyObserversOfChanges()
+    private void validateAndNotifyObserversOfChanges()
     {
-        clientModel.notifyObserversOfChanges(newDataSetInfo);
+        clientModel.validateNewDataSetInfoAndNotifyObservers(newDataSetInfo);
+        syncErrors();
     }
 
     private void setOwnerType(DataSetOwnerType type)
@@ -481,7 +487,7 @@ public class DataSetMetadataPanel extends JPanel
         NewDataSetDTOBuilder builder = newDataSetInfo.getNewDataSetBuilder();
         builder.setDataSetOwnerType(type);
 
-        notifyObserversOfChanges();
+        validateAndNotifyObserversOfChanges();
     }
 
     protected void setOwnerId(String text)
@@ -493,7 +499,58 @@ public class DataSetMetadataPanel extends JPanel
 
         NewDataSetDTOBuilder builder = newDataSetInfo.getNewDataSetBuilder();
         builder.setDataSetOwnerIdentifier(text);
-        notifyObserversOfChanges();
+        validateAndNotifyObserversOfChanges();
+    }
+
+    public void syncErrors()
+    {
+        // Clear all errors first
+        clearError(ownerIdLabel, ownerIdText);
+        clearError(dataSetFileLabel, dataSetFileComboBox);
+
+        List<ValidationError> errors = newDataSetInfo.getValidationErrors();
+        for (ValidationError error : errors)
+        {
+            switch (error.getTarget())
+            {
+                case DATA_SET_OWNER:
+                    displayError(ownerIdLabel, ownerIdText, error);
+                    break;
+
+                case DATA_SET_TYPE:
+                    // These are handled by the Metadata Panel
+                    break;
+
+                case DATA_SET_FILE:
+                    displayError(dataSetFileLabel, dataSetFileComboBox, error);
+                    break;
+
+                case DATA_SET_PROPERTY:
+                    // These are handled by the Properties Panel
+                    break;
+            }
+        }
+
+        for (DataSetPropertiesPanel panel : propertiesPanels.values())
+        {
+            panel.syncErrors();
+        }
+    }
+
+    private void displayError(JLabel label, JComponent component, ValidationError error)
+    {
+        // Not all errors are applicable to this panel
+        if (null == label || null == component)
+        {
+            return;
+        }
+        UiUtilities.displayError(label, component, error);
+    }
+
+    private void clearError(JLabel label, JComponent component)
+    {
+        UiUtilities.clearError(label, component);
+        component.setToolTipText(label.getToolTipText());
     }
 
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPropertiesPanel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPropertiesPanel.java
index 5b78a235a7023d616e21a53e13081de234f93a14..5595c4ef92b5b9e525907689e299c6c69feb6df6 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPropertiesPanel.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetPropertiesPanel.java
@@ -86,6 +86,8 @@ public class DataSetPropertiesPanel extends JPanel
 
     private final HashMap<String, JComponent> formFields = new HashMap<String, JComponent>();
 
+    private final HashMap<String, JLabel> labels = new HashMap<String, JLabel>();
+
     private NewDataSetInfo newDataSetInfo;
 
     public DataSetPropertiesPanel(DataSetType dataSetType, DataSetUploadClientModel clientModel)
@@ -143,6 +145,7 @@ public class DataSetPropertiesPanel extends JPanel
         String labelString = getLabelStringForPropertyType(propertyType);
         JLabel label = new JLabel(labelString + ":", JLabel.TRAILING);
         label.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT));
+        label.setToolTipText(propertyType.getDescription());
         if (propertyType.isMandatory())
         {
             // Set the font to be bold/italic for required fields.
@@ -157,15 +160,16 @@ public class DataSetPropertiesPanel extends JPanel
         {
             formField = createTextField(propertyType);
         }
+        formField.setToolTipText(propertyType.getDescription());
         formField.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
         addFormField(col, row, label, formField);
+        labels.put(propertyType.getCode(), label);
         formFields.put(propertyType.getCode(), formField);
     }
 
     private JTextField createTextField(final PropertyType propertyType)
     {
         final JTextField textField = new JTextField();
-        textField.setToolTipText(propertyType.getDescription());
         textField.addActionListener(new ActionListener()
             {
                 public void actionPerformed(ActionEvent e)
@@ -192,7 +196,6 @@ public class DataSetPropertiesPanel extends JPanel
     private JComboBox createComboBox(final ControlledVocabularyPropertyType propertyType)
     {
         final JComboBox comboBox = new JComboBox();
-        comboBox.setToolTipText(propertyType.getDescription());
         for (VocabularyTerm term : propertyType.getTerms())
         {
             comboBox.addItem(new VocabularyTermAdaptor(term));
@@ -257,6 +260,8 @@ public class DataSetPropertiesPanel extends JPanel
         }
         metadata.setProperties(newProps);
 
+        clientModel.validateNewDataSetInfoAndNotifyObservers(newDataSetInfo);
+        syncErrors();
         clientModel.notifyObserversOfChanges(newDataSetInfo);
     }
 
@@ -288,4 +293,54 @@ public class DataSetPropertiesPanel extends JPanel
         }
     }
 
+    public void syncErrors()
+    {
+        // Clear all errors first
+        for (String key : labels.keySet())
+        {
+            clearError(labels.get(key), formFields.get(key));
+        }
+
+        List<ValidationError> errors = newDataSetInfo.getValidationErrors();
+        for (ValidationError error : errors)
+        {
+            switch (error.getTarget())
+            {
+                case DATA_SET_OWNER:
+                    // These are handled by the Metadata Panel
+                    break;
+
+                case DATA_SET_TYPE:
+                    // These are handled by the Metadata Panel
+                    break;
+
+                case DATA_SET_FILE:
+                    // These are handled by the Metadata Panel
+                    break;
+
+                case DATA_SET_PROPERTY:
+                    JLabel label = labels.get(error.getPropertyCodeOrNull());
+                    JComponent formField = formFields.get(error.getPropertyCodeOrNull());
+                    displayError(label, formField, error);
+                    break;
+            }
+        }
+    }
+
+    private void displayError(JLabel label, JComponent component, ValidationError error)
+    {
+        // Not all errors are applicable to this panel
+        if (null == label || null == component)
+        {
+            return;
+        }
+        UiUtilities.displayError(label, component, error);
+    }
+
+    private void clearError(JLabel label, JComponent component)
+    {
+        UiUtilities.clearError(label, component);
+        component.setToolTipText(label.getToolTipText());
+    }
+
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java
index 87d0fa99e1426c60d5ff4312d5ceb9eef7dd7c3f..e7abcc5e703f705f7d13ee069523bf4f1cf5f4df 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetUploadClientModel.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -34,6 +35,7 @@ import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTOBuilder;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetMetadataDTO;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType;
@@ -61,7 +63,7 @@ public class DataSetUploadClientModel
     private final ArrayList<File> userSelectedFiles = new ArrayList<File>();
 
     // References to UI elements that are looking at the client model -- a way of implementing
-    // obeserver.
+    // observer.
     private DataSetUploadTableModel tableModel;
 
     public DataSetUploadClientModel(DssCommunicationState commState, ITimeProvider timeProvider)
@@ -110,6 +112,9 @@ public class DataSetUploadClientModel
 
         private long numberOfBytesUploaded;
 
+        private final ArrayList<ValidationError> validationErrors =
+                new ArrayList<ValidationError>();
+
         private NewDataSetInfo(NewDataSetDTOBuilder newDataSetBuilder, ITimeProvider timeProvider)
         {
             this.newDataSetBuilder = newDataSetBuilder;
@@ -190,7 +195,23 @@ public class DataSetUploadClientModel
         public boolean canBeQueued()
         {
             return status != Status.UPLOADING && status != Status.STALLED
-                    && status != Status.COMPLETED_UPLOAD;
+                    && status != Status.COMPLETED_UPLOAD && hasErrors() == false;
+        }
+
+        public boolean hasErrors()
+        {
+            return validationErrors.isEmpty() == false;
+        }
+
+        public List<ValidationError> getValidationErrors()
+        {
+            return validationErrors;
+        }
+
+        private void setValidationErrors(List<ValidationError> errors)
+        {
+            validationErrors.clear();
+            validationErrors.addAll(errors);
         }
     }
 
@@ -203,7 +224,7 @@ public class DataSetUploadClientModel
     }
 
     /**
-     * Add a new data set info to the list of data set info objectss and return it.
+     * Add a new data set info to the list of data set info objects and return it.
      */
     public NewDataSetInfo addNewDataSetInfo()
     {
@@ -212,6 +233,7 @@ public class DataSetUploadClientModel
         newDataSetBuilder.getDataSetMetadata().setDataSetTypeOrNull(defaultDataSetTypeCode);
         NewDataSetInfo newDataSetInfo = new NewDataSetInfo(newDataSetBuilder, timeProvider);
         newDataSetInfos.add(newDataSetInfo);
+        validateNewDataSetInfoAndNotifyObservers(newDataSetInfo);
         return newDataSetInfo;
     }
 
@@ -366,4 +388,76 @@ public class DataSetUploadClientModel
     {
         return userSelectedFiles;
     }
+
+    /**
+     * Validate a new data set info and update the validation errors.
+     */
+    public final void validateNewDataSetInfoAndNotifyObservers(NewDataSetInfo newDataSetInfo)
+    {
+        validateNewDataSetInfo(newDataSetInfo);
+        notifyObserversOfChanges(newDataSetInfo);
+    }
+
+    /**
+     * Validate a new data set info and update the validation errors.
+     */
+    public final void validateNewDataSetInfo(NewDataSetInfo newDataSetInfo)
+    {
+        ArrayList<ValidationError> errors = new ArrayList<ValidationError>();
+        validateNewDataSetInfo(newDataSetInfo, errors);
+        newDataSetInfo.setValidationErrors(errors);
+    }
+
+    /**
+     * This method actually carries out the validation. Subclasses may override.
+     */
+    protected void validateNewDataSetInfo(NewDataSetInfo newDataSetInfo,
+            ArrayList<ValidationError> errors)
+    {
+        NewDataSetDTOBuilder builder = newDataSetInfo.getNewDataSetBuilder();
+        String identifier = builder.getDataSetOwner().getIdentifier();
+        if (identifier == null || identifier.trim().length() < 1)
+        {
+            errors.add(ValidationError.createOwnerValidationError("An owner must be specified."));
+        }
+
+        if (null == builder.getFile())
+        {
+            errors.add(ValidationError.createFileValidationError("A file must be specified."));
+        }
+
+        NewDataSetMetadataDTO builderMetadata = builder.getDataSetMetadata();
+        String typeCode = builderMetadata.tryDataSetType();
+        if (null == typeCode)
+        {
+            errors.add(ValidationError
+                    .createDataSetTypeValidationError("A data set type must be specified."));
+        } else
+        {
+            DataSetType type = dataSetTypes.get(getIndexOfDataSetType(typeCode));
+            Map<String, String> properties = builderMetadata.getProperties();
+            for (PropertyTypeGroup ptGroup : type.getPropertyTypeGroups())
+            {
+                for (PropertyType propertyType : ptGroup.getPropertyTypes())
+                {
+                    validatePropertyType(propertyType, properties.get(propertyType.getCode()),
+                            errors);
+                }
+            }
+        }
+    }
+
+    private void validatePropertyType(PropertyType propertyType, String valueOrNull,
+            ArrayList<ValidationError> errors)
+    {
+        if (null == valueOrNull || valueOrNull.trim().length() < 1)
+        {
+            if (propertyType.isMandatory())
+            {
+                errors.add(ValidationError.createPropertyValidationError(propertyType.getCode(),
+                        "A value must be provided."));
+            }
+        }
+
+    }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/FileDetailsTableCellRenderer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/FileDetailsTableCellRenderer.java
deleted file mode 100644
index e4f5318c6304f688ac0db1651522d2500917b904..0000000000000000000000000000000000000000
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/FileDetailsTableCellRenderer.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2009 ETH Zuerich, CISD
- *
- * Licensed 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 ch.systemsx.cisd.openbis.dss.client.api.gui;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Font;
-import java.awt.GridLayout;
-import java.io.File;
-import java.util.Formatter;
-
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTable;
-import javax.swing.table.TableCellRenderer;
-
-import ch.systemsx.cisd.openbis.dss.client.api.gui.DataSetUploadClientModel.NewDataSetInfo;
-
-/**
- * Shows file name and file size in a table cell
- * 
- * @author Chandrasekhar Ramakrishnan
- */
-
-public class FileDetailsTableCellRenderer implements TableCellRenderer
-{
-    // Constants for computing the size of a file in the right units
-    private static final long KB = 1024L;
-
-    private static final long MB = 1024L * KB;
-
-    private final JLabel fileName = new JLabel();
-
-    private final JLabel fileSize = new JLabel();
-
-    private final JPanel panel = new JPanel();
-
-    public FileDetailsTableCellRenderer()
-    {
-        fileSize.setFont(fileName.getFont().deriveFont(Font.PLAIN));
-        panel.setLayout(new GridLayout(2, 0));
-        panel.add(fileName);
-        panel.add(fileSize);
-        panel.setOpaque(true);
-    }
-
-    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
-            boolean hasFocus, int row, int column)
-    {
-        NewDataSetInfo newDataSetInfo = (NewDataSetInfo) value;
-        Color backgroundColor =
-                (isSelected) ? table.getSelectionBackground() : table.getBackground();
-        panel.setBackground(backgroundColor);
-
-        if (null == newDataSetInfo)
-        {
-            return panel;
-        }
-        File file = newDataSetInfo.getNewDataSetBuilder().getFile();
-        String fileString = (null != file) ? file.getName() : "";
-        fileName.setText(fileString);
-        fileSize.setText(numberOfBytesToDisplayString(newDataSetInfo.getTotalFileSize()));
-        return panel;
-    }
-
-    static String numberOfBytesToDisplayString(long numBytes)
-    {
-        final Formatter f = new Formatter();
-        float numKBytes = (float) numBytes / KB;
-        if (numKBytes < 1.f)
-        {
-            f.format("%d bytes", numBytes);
-            return f.toString();
-        }
-
-        if (numKBytes < 1000.f)
-        {
-            f.format("%.2f kB", numKBytes);
-            return f.toString();
-        }
-
-        float numMBytes = (float) numBytes / MB;
-        if (numMBytes < 1000.f)
-        {
-            f.format("%.2f MB", numMBytes);
-            return f.toString();
-        }
-
-        float numGBytes = numMBytes / KB;
-        f.format("%.2f GB", numGBytes);
-        return f.toString();
-    }
-}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UiUtilities.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UiUtilities.java
new file mode 100644
index 0000000000000000000000000000000000000000..e146055ddf95b56976df7c40ae3432a96130039c
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UiUtilities.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.openbis.dss.client.api.gui;
+
+import java.awt.Color;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class UiUtilities
+{
+
+    public static void displayError(JLabel label, JComponent component, ValidationError error)
+    {
+        component.setToolTipText(error.getErrorMessage());
+        label.setForeground(Color.RED);
+    }
+
+    public static void clearError(JLabel label, JComponent component)
+    {
+        component.setToolTipText(null);
+        label.setForeground(Color.BLACK);
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UploadStatusTableCellRenderer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UploadStatusTableCellRenderer.java
index 019cc94cdc1315551edbb93ae25477023ecb29c7..c2637d544890c89beaf4a0087b5cab0142f7c2ae 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UploadStatusTableCellRenderer.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/UploadStatusTableCellRenderer.java
@@ -41,6 +41,10 @@ public class UploadStatusTableCellRenderer implements TableCellRenderer
 
     private final JPanel uploadPanel = new JPanel();
 
+    private final JLabel fixErrorsLabel = new JLabel("Incomplete (see fields in red)");
+
+    private final JPanel fixErrorsPanel = new JPanel();
+
     private final JProgressBar progressBar = new JProgressBar();
 
     private final JLabel progressLabel = new JLabel();
@@ -60,12 +64,22 @@ public class UploadStatusTableCellRenderer implements TableCellRenderer
     public UploadStatusTableCellRenderer(DataSetUploadTableModel tableModel)
     {
         super();
+        createFixErrorsPanel();
         createDownloadPanel();
         createProgressPanel();
         createRetryPanel();
         createCompletedPanel();
     }
 
+    private void createFixErrorsPanel()
+    {
+        fixErrorsPanel.setLayout(new GridLayout(1, 0));
+        fixErrorsLabel.setFont(fixErrorsLabel.getFont().deriveFont(Font.PLAIN));
+        fixErrorsLabel.setForeground(Color.RED);
+        fixErrorsPanel.add(fixErrorsLabel);
+        fixErrorsPanel.setOpaque(true);
+    }
+
     private void createCompletedPanel()
     {
         completedPanel.setLayout(new GridLayout(1, 0));
@@ -110,7 +124,13 @@ public class UploadStatusTableCellRenderer implements TableCellRenderer
         switch (dataSetInfo.getStatus())
         {
             case TO_UPLOAD:
-                panel = uploadPanel;
+                if (dataSetInfo.hasErrors())
+                {
+                    panel = fixErrorsPanel;
+                } else
+                {
+                    panel = uploadPanel;
+                }
                 break;
             case QUEUED_FOR_UPLOAD:
             case UPLOADING:
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ValidationError.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ValidationError.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2ee1863fc11da82fd397e631316ca3888ed9b7d
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/ValidationError.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.openbis.dss.client.api.gui;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class ValidationError
+{
+    public static enum ValidationErrorTarget
+    {
+        DATA_SET_TYPE, DATA_SET_OWNER, DATA_SET_PROPERTY, DATA_SET_FILE
+    }
+
+    public static ValidationError createDataSetTypeValidationError(String errorMessage)
+    {
+        return new ValidationError(ValidationErrorTarget.DATA_SET_TYPE, null, errorMessage);
+    }
+
+    public static ValidationError createOwnerValidationError(String errorMessage)
+    {
+        return new ValidationError(ValidationErrorTarget.DATA_SET_OWNER, null, errorMessage);
+    }
+
+    public static ValidationError createPropertyValidationError(String propertyCode,
+            String errorMessage)
+    {
+        return new ValidationError(ValidationErrorTarget.DATA_SET_PROPERTY, propertyCode,
+                errorMessage);
+    }
+
+    public static ValidationError createFileValidationError(String errorMessage)
+    {
+        return new ValidationError(ValidationErrorTarget.DATA_SET_FILE, null, errorMessage);
+    }
+
+    private final ValidationErrorTarget target;
+
+    // Only non-null on property targets
+    private final String propertyCodeOrNull;
+
+    private final String errorMessage;
+
+    // Private Constructor -- use factory methods
+    private ValidationError(ValidationErrorTarget target, String propertyCodeOrNull,
+            String errorMessage)
+    {
+        this.target = target;
+        this.propertyCodeOrNull = propertyCodeOrNull;
+        this.errorMessage = errorMessage;
+    }
+
+    public ValidationErrorTarget getTarget()
+    {
+        return target;
+    }
+
+    public String getPropertyCodeOrNull()
+    {
+        return propertyCodeOrNull;
+    }
+
+    public String getErrorMessage()
+    {
+        return errorMessage;
+    }
+
+    @Override
+    public String toString()
+    {
+        ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
+        builder.append(target);
+        builder.append(propertyCodeOrNull);
+        builder.append(errorMessage);
+        return builder.toString();
+    }
+
+}